Wednesday, January 27, 2010

Writing a VBScript

'-------------------------
'Functions
'-------------------------
Function WriteRecordSet(aRecordSet,aFile)
Dim lRecordsetString
Dim lngFieldsIndex
Dim lngIndex
Dim lFieldValue
lRecordsetString = ""
lngFieldsIndex= aRecordSet.RecordCount - 1
For lngIndex = 0 to lngFieldsIndex
if lngIndex = 0 then
lRecordsetString = Cstr(aRecordSet.Fields(lngIndex).Name)
else
lRecordsetString = lRecordsetString & "" & Cstr(aRecordSet.Fields(lngIndex).Name)
end if
Next
aFile.WriteLine(lRecordsetString)
lRecordsetString = ""
aRecordSet.MoveFirst
Do While (Not aRecordSet.EOF)
For lngIndex = 0 to lngFieldsIndex
if (aRecordSet(lngIndex).Value = null) Then
lFieldValue = "DBNull"
else
lFieldValue = Cstr(aRecordSet(lngIndex).Value)
end if
if lngIndex = 0 then
lRecordsetString = lFieldValue
else
lRecordsetString = lRecordsetString & "" & lFieldValue
end if
Next
aFile.WriteLine(lRecordsetString)
aRecordSet.MoveNext
Loop
aRecordSet.MoveFirst
End Function

Function WriteArrayOfArray(aArrayOfArray,aFile)
Dim strArray
Dim lngUBound1
Dim lngUBound2
Dim lngIndex1
Dim lngIndex2
lngUBound1 = UBound(aArrayOfArray, 1)
lngUBound2 = UBound(aArrayOfArray, 2)
For lngIndex1 = 0 To lngUBound1
For lngIndex2 = 0 To lngUBound2
strArray = strArray + "[" & lngIndex1 & "," & lngIndex2 & "] = " & aArrayOfArray(lngIndex1, lngIndex2) & vbcrlf
Next
Next
aFile.WriteLine(strArray)
End Function

'-------------------------
'Start of your VB script
'-------------------------
Dim myFSO
Dim myFile
Set myFSO = CreateObject("Scripting.FileSystemObject")
Set myFile= myFSO.OpenTextFile("PadbVBScript.txt", 8, True)

Dim lPADBObject
set lPADBObject = CreateObject("IWebClientServ16.Profile","GMOBOSCRPAPP01R")
lPADBObject.setSqlServer = "GMOBOSCRPSQLR"
lPADBObject.formatOutput = True

Dim lRecordset
set lRecordset = CreateObject("ADODB.Recordset")
Dim lvRet
Dim lArray

set lRecordset = lPADBObject.getBenchmark(4004, "GMOBOSCRPSQLR")
myFile.WriteLine("<<>>")
WriteRecordSet lRecordset,myFile
myFile.WriteLine()

lvRet = lPADBObject.GetCountryWeights(1022,"8/31/2009","GMOBOSCRPSQLR",15,True)
myFile.WriteLine("<<>>")
WriteArrayOfArray lvRet,myFile
myFile.WriteLine()

lvRet = lPADBObject.GetChar(4002,"8/31/2009","GMOBOSCRPSQLR",,Array(4006),1)
lvRet = lPADBObject.toBaseCurrency(4002,"8/31/2009",lvRet,"GMOBOSCRPSQLR",True)
myFile.WriteLine("<<>>")
WriteArrayOfArray lvRet,myFile
myFile.WriteLine()

myFile.Close
set myFile = nothing
set myFSO = nothing
set lPADBObject = Nothing

VBS Functions

Monday, January 25, 2010

Finalize and Dispose

References:
Rules for Finalize and Dispose

Finalize and Dispose are all about freeing unmanaged resources such as files, streams, db connections etc. held by objects. While Dispose can be directly called by users of objects, Finalize is called by GC.

Do not assume Dispose will be called by the users/programmers using your object. You should always free up resources in Finalize as a back-up.

Calls must be propagated correctly through containmnet hierarchy i.e.
1. If object A has a reference to object B which in turn has reference to object C, then you must make sure that A.Dispose() code calls B.Dispose() (and B.Dispose() calls C.Dispose()).
2. A.Dispose() should also call A's base type's Dispose() if there is a base type implementing IDisposable.

When a class implements IDisposable, it is basically announcing it is using scarce resources. SAM: So your own object (whether stand-alone, abstract base or derived) can and should implement IDisposable, if it's holding references to unmanaged resources on its own or it contains objects that hold references to unmanaged resources. There is no reason why you can't implement your own IDisposable on an object that derives from another object that already implements that interface. However, depending on stand-alone, abstract or derived class you are coding, you may or may not have to implement your own IDisposable. Bottom line is, calling Dispose() by users should free up all the resources, containment-wise and object hierarchy-wise.

Close() should be a special case of Dispose(). Some unmanaged resources like streams have a state of either "open" or "closed", so it makes sense to provide a Close() method to the users of your class instead of Dispose(). However, calling Close() should internally call Dispose().




Example
==========

[C#]
using System;
using System.ComponentModel;

// The following example demonstrates how to create
// a resource class that implements the IDisposable interface
// and the IDisposable.Dispose method.

public class DisposeExample
{
// A base class that implements IDisposable.
// By implementing IDisposable, you are announcing that
// instances of this type allocate scarce resources.
public class MyResource: IDisposable
{
// Pointer to an external unmanaged resource.
private IntPtr handle;
// Other managed resource this class uses.
private Component component = new Component();
// Track whether Dispose has been called.
private bool disposed = false;

// The class constructor.
public MyResource(IntPtr handle)
{
this.handle = handle;
}

// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
// SAM: Comment on "do not make this virtual". True only if the class you are
// writing is the base class like this example. However, a lot of times, you
// would be writing a class, derived from another class (your own or supplied
// by a software vendor) that DOES make this method virtual and rightfully
// so. Look at ActiveReports software example below.

public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}

// Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
private void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// Dispose managed resources.
component.Dispose();
}

// Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
CloseHandle(handle);
handle = IntPtr.Zero;
}
disposed = true;
}

// Use interop to call the method necessary
// to clean up the unmanaged resource.
[System.Runtime.InteropServices.DllImport("Kernel32")]
private extern static Boolean CloseHandle(IntPtr handle);

// Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~MyResource()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}
}
public static void Main()
{
// Insert code here to create
// and use the MyResource object.
}
}






Active Reports Example
========================
Background info: From a client's standpoint, you call a method on a server
class "ProfileSummaryActiveReport" (which you also create but ultimately derive from
vendor's ActiveReports3 class) to render a report with "using". ActiveReport3 class
provides "virtual Dispose (bool disposing)" method. See how I have implemented my
client and server code to free up unmanaged resources and references to objects with
unmanaged resources. I could have implemented my own IDisposable on server class,
but I did not because I did not have to (since ActiveReport3 provided me the virtual
method to override).

Further, I architected "ProfileSummaryActiveReport" class to be simply a collection
of Activereports-provided SubReports. Each subreport is a ActiveReports-provided
tabular textual controls or it could be another vendor called ChartFX' chart control.

Idea is, when the client calls the method on ProfileSummaryActiveReport object
with "using", the Dispose() that fires should then propagate thru all objects in a
meaningful way i.e. call dispose() on each subreports.

//----------------------------------------------------------------------
Client calling

ProfileSummaryActiveReport lProfileSummaryActiveReport = null;
RenderReportResult lRenderReportResult = null;
using (lProfileSummaryActiveReport = new ProfileSummaryActiveReport(
aLogger,
lActiveReportCount,
lPageDataSet,
aReportParams,
pdfParams,
aProfileSummaryDiagnosticsInfo))
{
lRenderReportResult = lProfileSummaryActiveReport.RenderReport();
}

//----------------------------------------------------------------------
Servers

//Write your own server-based active report (must derive from vendor
//supplied class ActiveReport3) that serves as a container for subreports

public partial class ProfileSummaryActiveReport : ActiveReportBase
{
public List ListOfSubReportWrapper = new List();

public List ListOfPlaceholderSubReportWrapper = new List();

private void DisposeSubReports()
{
foreach (SubReportWrapper lSRW in this.ListOfSubReportWrapper)
{
lSRW.ARSubReport.Dispose();
}

foreach (SubReportWrapper lSRW in this.ListOfPlaceholderSubReportWrapper)
{
lSRW.ARSubReport.Dispose();
}
if (this.ReportPageFootnotes != null)
this.ReportPageFootnotes.Clear();

if (this.SubReportForcedHeightInfoList != null)
this.SubReportForcedHeightInfoList.Clear();

foreach (KeyValuePair lKVP in this.mDictionaryProfileSummarySubReport)
{
if (lKVP.Value.SubReportDataSet!=null)
lKVP.Value.SubReportDataSet.Dispose();
}
}


//blah blah
}

partial class ProfileSummaryActiveReport
{
///
/// Clean up any resources being used.
///

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (this.mReadyToDisposeSubReportsIfAny)
{
this.DisposeSubReports();
}
}
base.Dispose(disposing);
}

private DataDynamics.ActiveReports.Detail detail;
//blah blah
}

//----------------------------------------------------------------------

public partial class ActiveReportBase : DataDynamics.ActiveReports.ActiveReport3
{
protected System.Data.DataSet mReportData = null;

public byte[] CombineReportsAsPDFByteArray(Dictionary aDictionaryOfReports)
{
DataDynamics.ActiveReports.ActiveReport3 lActiveReport = new ActiveReport3();
int lPageNumber = 0;
foreach (KeyValuePair kvp in aDictionaryOfReports)
{
lPageNumber++;
using (MemoryStream lMemoryStream = new MemoryStream(kvp.Value))
{
this.Document.Load(lMemoryStream);
foreach (Page lPage in this.Document.Pages)
{
lActiveReport.Document.Pages.Add(lPage);
}
}
}

using (MemoryStream lMemoryStream = new MemoryStream())
{
using (PdfExport lPdfExport = new PdfExport())
{
lPdfExport.Export(lActiveReport.Document, lMemoryStream);
}
lMemoryStream.Flush();
lActiveReport.Dispose();
this.mReadyToDisposeSubReportsIfAny = true;
return lMemoryStream.ToArray();
}
}

//blah blah
}

partial class ActiveReportBase
{

///
/// Clean up any resources being used.
///

protected override void Dispose(bool disposing)
{
if (disposing)
{

}
base.Dispose(disposing);
}

private DataDynamics.ActiveReports.Detail detail;
//blah blah

}

//----------------------------------------------------------------------

public partial class GanttChartFX : ProfileSummarySubReportARBase, IBarBasedChart
{
private ChartFX.WinForms.Chart mChart = null;
private DataDynamics.ActiveReports.CustomControl mCustomControl = null;

//blah
}

partial class GanttChartFX
{

///
/// Clean up any resources being used.
///

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (this.mChart != null)
this.mChart.Dispose();

if (this.mCustomControl != null)
this.mCustomControl.Dispose();
}
base.Dispose(disposing);
}

private DataDynamics.ActiveReports.Detail detail;
// blah
}

//----------------------------------------------------------------------

public abstract partial class ProfileSummarySubReportARBase : DataDynamics.ActiveReports.ActiveReport3, IProfileSummarySubReportRenderer, IPlaceholderSubReportHost
{
// blah
}

partial class ProfileSummarySubReportARBase
{

///
/// Clean up any resources being used.
///

protected override void Dispose(bool disposing)
{
if (disposing)
{
}
base.Dispose(disposing);
}

private DataDynamics.ActiveReports.Detail detail;
// blah
}

Monday, January 11, 2010

Total Recorder Drivers - 3 kinds

Total Recorder Drivers

Sam: When recording from internet radio,

(1) go to TR's recording source and parameters and make sure you choose "software" instead of "sound board" for audio recording source.
(2) go to TR's settings->Driver, choose "Kernel-mode filter driver" and "any playback device" under playback and recording.


Selecting the type of driver to be installed with Total Recorder

Total Recorder has three types of audio drivers:

User-mode virtual device driver. This is the same type of driver that has been supplied since the first version of Total Recorder.
Kernel-mode virtual device driver, which was added in version 7.0.
Kernel-mode filter driver, which was added in version 8.0.
When installing Total Recorder, you can select any combination of Total Recorder drivers to be installed, or you can select not to install a driver. It is recommended you choose one of the following configurations during installation:

Simple configuration.

Install Total Recorder with the kernel-mode filter driver only.
This configuration is suitable in most cases because of its ease-of-use, an absence of undesirable effects due to additional drivers, and the main features of software recording, except for accelerated and silent recording, can be used.
Advanced configuration.
For Windows XP:
Install Total Recorder with the user-mode driver and the kernel-mode filter driver.
For Windows Vista and later:
Install Total Recorder with both the kernel-mode drivers (virtual device driver and filter driver).

This configuration provides the ability to use almost all of the features of software recording. More complex Total Recorder settings may be required especially if several sound devices are used.
Restricted configuration
Install Total Recorder without a driver.
If you install Total Recorder without a driver, you will not be able to record in Software mode. An alternative to Software mode recording is to record in Soundboard mode from a line such as "Stereo Mix", "Wave", "What U hear", or similar. Most sound boards have such a line. Installing Total Recorder without a driver may be necessary if you encounter compatibility problems between the Total Recorder drivers and other software.

If you install Total Recorder with more than one driver, you can select which driver Total Recorder uses.

To install or uninstall a driver, you must reinstall Total Recorder over the installed instance and select the appropriate driver options during installation. All of Total Recorder's settings and registration information are preserved except for any settings that are incompatible with the new driver's configuration.

Comparing Different Types of Total Recorder Drivers
User-mode virtual device driver

Advantages
Sound is captured exactly in the same format that is used by an audio player to pass audio data to a sound board.
Sound can be captured from specific applications.
Accelerated recording is faster and more reliable.
Disadvantages
This type of driver is not fully supported by modern operating systems. For Windows XP, you may find incompatibilities with some applications. For Windows Vista and later operating systems, most applications cannot be recorded with this driver. See information below.
Kernel-mode drivers (virtual device driver and filter driver)

Advantages
These drivers are fully compatible with modern operating systems.
The kernel-mode filter driver does not require any change to your system audio settings.
Disadvantages
Sound is captured after it has been processed (mixed, resampled) by the operating system. This results in the following:
- You cannot restrict recording to a particular application.
- Additional conversions of the format may be performed.
- Volume regulators can affect the sound being captured.

Accelerated recording through the kernel-mode virtual device driver is slower and less reliable. Accelerated recording through the kernel-mode filter driver cannot be done at all.
You may experience other problems. For more information, see below.
Advantages of the kernel-mode filter driver over the kernel-mode virtual device driver

The kernel-mode filter driver does not add a sound device in your system whereas the kernel-mode virtual device driver does. When using the kernel-mode filter driver, no special configuration of system audio devices or devices used by a program to be recorded is required.
The kernel-mode filter driver does not result in problems with USB microphones on Windows XP.
Advantages of kernel-mode virtual device driver over the kernel-mode filter driver

The kernel-mode virtual device driver can record in accelerated mode and in silent mode.
If the kernel-mode virtual device driver is used, usually you can configure your system and sound applications so that only the application’s sounds will be recorded. If the kernel-mode filter driver is used, recording a particular application can be achieved only if there is more than one real sound playback device on your system.
After installing the kernel-mode filter driver, a reboot is always required. After installing the kernel-mode virtual device driver, a reboot is not usually required.
Possible Problems with Total Recorder Drivers

Possible problems with Total Recorder's user-mode driver
- Incompatibility with DirectSound

Problems can occur with an application that uses Direct Sound. If such an application passes a sound stream through the driver, the sound may be garbled. For example, distortions often appear when using most versions of Skype 3.x.

- Incompatibility with a small number of applications

A small number of applications may not start at all, or they may function incorrectly, if the driver is set as a system default device. Examples of such applications include CyberLink software (e.g. PowerDVD, PowerProducer) and Adobe software (e.g. Adobe Premiere, Adobe Encore, etc.).
- Partial compatibility with Windows Vista

See this information regarding compatibility issues between the user-mode driver and Windows Vista.
Possible problems with Total Recorder's kernel-mode driver (virtual device driver or filter driver)

- Unable to record a particular application

The system mixes audio streams being played before it arrives in the kernel-mode driver. Audio streams being played can only be recorded in mixed form. This is similar to recording from a line such as "Stereo Mix". It is not possible to single out a stream belonging to a particular application as it could be made using a user-mode driver. All appropriate recording parameters (i.e. Record only streams opened after the recording has started and Record only this application) are disabled.
- Volume regulator affects the level of recording

The volume level of the Wave line affects the level of sound received by the kernel-mode driver. For quality recordings, it is recommended you set the volume level of the Wave line to the maximum position and do not change this level during the recording. You should use the level of the Master line to regulate the sound volume when recording.

Notes:

Most players' volume regulators are connected to the Wave line. You should set the regulator to the maximum position and do not change it during a recording.
The system volume regulator, which is the regulator that appears when you click on the system tray icon, is associated with the Master line. You can adjust it freely while recording.
Under Windows XP, you can also use the volume regulator in Total Recorder's main window to adjust volume. Beginning with version 7.0, this regulator is associated with the Master line rather than the Wave line. Under Windows Vista, you should use only the system volume regulator.
- Accelerated recording through the kernel-mode filter driver cannot be performed

If Total Recorder is set to use the kernel-mode filter driver then Total Recorder cannot record in accelerated recording mode.
- Additional format conversion is sometimes performed

When a playback program passes a sound stream to the sound board, Windows can transform this sound stream to a format supported by your sound board. Total Recorder's kernel-mode driver receives this transformed stream rather than the original stream. The driver does not know the format of the original stream and Total Recorder can display only the format of the transformed stream.

In very rare cases, this conversion can result in a minor loss of quality, although this loss is normally not audible. Since the majority of recordings are performed in a compressed format, the compression results in more loss in quality (even if it is usually not audible) than the conversion.

Possible problems specific to Total Recorder's kernel-mode virtual device driver
- For some sound boards, a sound stream cannot be played through the board while another stream is played through the kernel-mode driver if the driver is set to use the sound board

This restriction can cause some problems:
If an application plays silence continuously and the application cannot be closed, then switching a system default device may require you to restart your system or to log off and on before your sound program will work properly.
You cannot record a particular sound stream by directing the stream to Total Recorder's kernel-mode driver while directing all other sound streams to the real sound board.
Note that this problem does not occur with most sound boards.
- Incompatibility with USB-microphones under Windows XP

Total Recorder's kernel-mode driver does not work with USB microphones under Windows XP. This can result in problems when recording an Internet telephony program, such as Skype. Such programs can be recorded, however this requires some additional setup. For more information, see Total Recorder Help: Troubleshooting -> After installing Total Recorder with the kernel-mode driver, problems occur using a USB microphone.

Note that this problem does not occur on Windows Vista.
- Problems with accelerated recording

The speed of an accelerated recording can be lower when using the kernel-mode driver compared with the user-mode driver. The recorded sound may be garbled even though no problems appeared when the recording was being made. For more information, see Total Recorder Help: Using Total -> Recorder Recording -> Accelerated Recording.
- Driver's recording-level regulator may function improperly

It is possible that the recording level regulator or the volume for specific playback lines of the driver does not work. This depends on the particular sound board. If you encounter this problem, follow these recommendations:
For Windows 2000/XP: Launch the system mixer, and use the controls of the real sound board rather than the controls of Total Recorder's driver.
For Windows Vista: From the Control Panel, click Sounds (or select Options - System settings in Total Recorder's main menu), select the playback or recording device to be used, click the Properties button, and then go to the Levels tab.
- Under Windows 2000/XP, if you record from Total Recorder's kernel-mode driver device, you should manually select the recording line

Total Recorder's kernel-mode driver has only one recording line, called "Microphone". Recording actually occurs through the active recording line of a real sound board. If you find that a recording uses an incorrect line, you should manually select the proper recording line by using the system mixer.
This problem occurs mostly when recording Internet telephony programs, such as Skype. If you only want to record from a sound board, you should record directly from a real sound device rather than from Total Recorder's driver.
- Under Windows Vista, if you record from Total Recorder's kernel-mode driver device, the recording can use an incorrect line

If you use Total Recorder's kernel-mode driver to record from a recording device, sometimes the recording uses an incorrect line. This problem depends on the real soundboard driver.
This problem occurs mostly when recording Internet telephony programs, such as Skype. If you only want to record from a sound board, you should record directly from a real sound device rather than from Total Recorder's driver.
If this problem occurs, take the following steps:
Stop using the recording device, and terminate the Internet-telephony conversation.
From the Control Panel, click Sounds (or select Options - System settings in Total Recorder's main menu), and then go to the Recording tab.
Select a real device (normally a microphone) that should be used for capturing sound, and click the Set Default button
Select Microphone. Total Recorder kernel mode (WDM) audio driver, and click the Set Default button.

Close the Sounds window.
See also:

Primer on PC Audio

Thursday, January 7, 2010

SQL Server UDTs

Msg 2715, Level 16, State 7, Procedure SPregInsertRegressionTop1Report, Line 70
Column, parameter, or variable #1: Cannot find data type DTObjectID.

Above error ocurred on CRPCORE db on my local computer. The UDT DTObjectID does exist in db CRPCORE (under Programmability.Types.User-defined Data Types).

Problem: UDTs must be known to SQL server before they can be used i.e these UDTs must also exist in model and tempdb databases. Im my case, esp tempdb because the SP above internally creates a table (with create TABLE) which, as we all know, gets created in tempdb.

Resolution: import these UDTs to model and tempdb.

Monday, January 4, 2010

drop database

-- drop kick any connections to database "foo" and roll back their transactions
ALTER DATABASE foo
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE

-- Drop the database "foo"
USE MASTER
GO

DROP DATABASE foo