<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8436642170609457318</id><updated>2012-01-04T13:51:49.924+01:00</updated><category term='Controls'/><category term='C++/CLI'/><category term='TeamBuild'/><category term='SMO'/><category term='DTS'/><category term='Windows'/><category term='MFC'/><category term='Designer'/><category term='WiX'/><category term='Sharepoint'/><category term='SQL Server'/><title type='text'>Bart's Software Cookbook</title><subtitle type='html'>computer related problem solving</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bartjolling.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bartjolling.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Bart</name><uri>http://www.blogger.com/profile/01531240801317106633</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8436642170609457318.post-5252296642751447676</id><published>2010-08-04T21:06:00.022+02:00</published><updated>2010-08-04T22:17:11.279+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sharepoint'/><title type='text'>Create a bug progress report from a Sharepoint 2003 bug list</title><content type='html'>&lt;p&gt;Sharepoint 2003 includes a list template for bug tracking. It provides very basic functionality like keeping bug statuses, description, comments, dates, assignments etc. For every update that is made to a bug report, Sharepoint just adds a new item to the list. It doesn't however include a bug progress report.
&lt;/p&gt;&lt;p&gt;In order to create such a report, I will create a new view on the bug report list in Sharepoint in order to expose the necessary information. In MS Access I will created a linked table that allows us to perform queries on the data to put it in the correct format for use in a pivot table. This pivot table and pivot chart will contain the bug progress report.
&lt;/p&gt;
&lt;span style="font-size:130%;"&gt;Sharepoint bug reports: progress details&lt;/span&gt;&lt;p&gt;
On the sharepoint bug list, create a new view containing the following fields:
&lt;ul&gt;&lt;li&gt;Id&lt;/li&gt;&lt;li&gt;Issue Id&lt;/li&gt;&lt;li&gt;Status&lt;/li&gt;&lt;li&gt;Modified&lt;/li&gt;&lt;li&gt;Current&lt;/li&gt;&lt;/ul&gt;This will give you the entire history for every Issue but from this information you can't yet determine when a bug changed from one status to another.&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:130%;"&gt;MS Access linked tables&lt;/span&gt;&lt;/p&gt;&lt;p&gt;In order to create a bug progress report, we need to build a list of status changes for each of the issues. I have created four queries for the different situations that can occur.&lt;/p&gt;&lt;p&gt;The "StatusSequenceHistory" query determines the sequence of Ids of bug reports for each Issue Id. For each change it collects what Id was changed (FromId) and which new Id was created (ToId)&lt;/p&gt;
&lt;pre name="code" class="sql"&gt;
SELECT fr.[Issue Id] AS IssueId,
       fr.Id AS FromId,
       fr.Status AS FromStatus,
       min(to.Id) AS ToId
FROM [Bug Reports: Progress Details] AS fr
LEFT JOIN [Bug Reports: Progress Details] AS [to]
ON fr.[Issue Id]=to.[Issue Id]
WHERE fr.Id &amp;lt; to.Id
  AND to.Current=False
  AND fr.Current=False
GROUP BY fr.[Issue Id], fr.Id, fr.Status
ORDER BY fr.[Issue Id], fr.id;&lt;/pre&gt;&lt;p&gt;Not all status will have a ToId and a FromId. The "StatusSequenceNew" query selects bug reports that have just been created but do not have a history yet.&lt;/p&gt;&lt;pre name="code" class="sql"&gt;
SELECT [Issue Id] AS IssueId, min(Id) AS ToId
FROM [Bug Reports: Progress Details]
GROUP BY [Issue Id]
HAVING Count(Id) = 1;
&lt;/pre&gt;

&lt;p&gt;The "StatusSequenceFirst" query selects the very first bug report that was created.&lt;/p&gt;
&lt;pre name="code" class="sql"&gt;
SELECT [Issue Id] AS IssueId, min(Id) AS ToId
FROM [Bug Reports: Progress Details]
WHERE Current=False
GROUP BY [Issue Id];&lt;/pre&gt;&lt;p&gt;The "StatusSequenceLast" query selects the final bug report that was created which in fact is the current version of the bug report&lt;/p&gt;&lt;pre name="code" class="sql"&gt;
SELECT fr.[Issue Id] AS IssueId,
       max(fr.Id) AS FromId,
       to.Status AS ToStatus,
       to.Id AS ToId
FROM [Bug Reports: Progress Details] AS fr
LEFT JOIN [Bug Reports: Progress Details] AS [to]
ON fr.[Issue Id]=to.[Issue Id]
WHERE fr.Id &amp;gt; to.Id
AND to.Current=True
AND fr.Current=False
GROUP BY fr.[Issue Id], to.id, to.Status
ORDER BY fr.[Issue Id], to.id;
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;The StatusSequence query&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;This query joins the complete history together and adds the status for each change&lt;/p&gt;&lt;pre name="code" class="sql"&gt;(
SELECT IssueId,FromId, FromStatus, ToId, det.Status as ToStatus
FROM StatusSequenceHistory old
LEFT JOIN [Bug Reports: Progress Details] det
ON old.ToId = det.Id
)
UNION (
SELECT IssueId,FromId, det.Status as FromStatus, ToId, ToStatus
FROM StatusSequenceLast cur
LEFT JOIN [Bug Reports: Progress Details] det
ON cur.FromId = det.Id
)
UNION (
SELECT IssueId, NULL as FromId, NULL as FromStatus, ToId, det.Status as ToStatus
FROM StatusSequenceFirst fir
LEFT JOIN [Bug Reports: Progress Details] det
ON fir.ToId =det.Id
)
UNION (
SELECT IssueId, NULL as FromId, NULL as FromStatus, ToId, det.Status as ToStatus
FROM StatusSequenceNew new
LEFT JOIN [Bug Reports: Progress Details] det
ON new.ToId =det.Id
);
&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;The ProgressReport query&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;This query adds the number of status changes for each change and for each day&lt;/p&gt;&lt;pre name="code" class="sql"&gt;(
SELECT
Int(d.Modified) AS ModifiedDate, s.FromStatus AS Status, -1 * COUNT(s.FromStatus) as Diff
FROM StatusSequence s
RIGHT JOIN [Bug Reports: Progress Details] d
ON s.ToId = d.Id
WHERE s.FromStatus &lt;&gt; ''
GROUP BY Int(d.Modified), s.FromStatus
)
UNION (
SELECT
Int(d.Modified) AS ModifiedDate, s.ToStatus AS Status, 1 * COUNT(s.ToStatus) as Diff
FROM StatusSequence s
LEFT JOIN [Bug Reports: Progress Details] d
ON s.ToId = d.Id
GROUP BY Int(d.Modified), s.ToStatus
);

&lt;/pre&gt;
&lt;span style="font-size:130%;"&gt;Microsoft Excel: Bug progress report&lt;/span&gt;&lt;p&gt;
In Excel you can now create a link to the MS Access database as an external source. Choose the PivotTable/PivotChart option when connecting. Put the Modified Date in the left column of the PivotTable, the Status in the upper row and the Issue Id as in the data fields. Configure the Ids in order to show as a running total&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8436642170609457318-5252296642751447676?l=bartjolling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bartjolling.blogspot.com/feeds/5252296642751447676/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8436642170609457318&amp;postID=5252296642751447676' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/5252296642751447676'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/5252296642751447676'/><link rel='alternate' type='text/html' href='http://bartjolling.blogspot.com/2010/08/create-bug-progress-report-from.html' title='Create a bug progress report from a Sharepoint 2003 bug list'/><author><name>Bart</name><uri>http://www.blogger.com/profile/01531240801317106633</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8436642170609457318.post-186418540968356453</id><published>2010-01-16T08:49:00.010+01:00</published><updated>2010-01-19T11:46:39.059+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows'/><title type='text'>Windows Activation: No records found for given DNS query.</title><content type='html'>&lt;br/&gt;
I recently installed Windows 7 Enterprise Edition on one of my PC. Eager to get my PC up and running with all software I daily use, I skipped activation.

When I tried to activate a few days later, I was greeted by this error message:
&lt;a href="http://3.bp.blogspot.com/_oymlMPJmD08/S1FwVkphmNI/AAAAAAAAABg/xfgkMQzPAGo/s1600-h/Activation.PNG"&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 320px; DISPLAY: block; HEIGHT: 211px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5427242541875566802" border="0" alt="No records found for given DNS query" src="http://3.bp.blogspot.com/_oymlMPJmD08/S1FwVkphmNI/AAAAAAAAABg/xfgkMQzPAGo/s320/Activation.PNG" /&gt;&lt;/a&gt;Searching for this message, you might end up on this &lt;a href="http://support.microsoft.com/default.aspx/kb/938450"&gt;Microsoft support page&lt;/a&gt; telling you to check you DNS settings. In my case this didn't apply at all.
&lt;p&gt;In the end it turns out that I ot this message because I hadn't entered my product key yet because I skipped activation during setup. To solve the issue, I:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;went to "Control Panel\System and Security\System" &lt;/li&gt;&lt;li&gt;clicked "change product key"&lt;/li&gt;&lt;li&gt;entered a valid product key&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Windows automatically activated.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8436642170609457318-186418540968356453?l=bartjolling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bartjolling.blogspot.com/feeds/186418540968356453/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8436642170609457318&amp;postID=186418540968356453' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/186418540968356453'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/186418540968356453'/><link rel='alternate' type='text/html' href='http://bartjolling.blogspot.com/2010/01/windows-activation-no-records-for-for.html' title='Windows Activation: No records found for given DNS query.'/><author><name>Bart</name><uri>http://www.blogger.com/profile/01531240801317106633</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_oymlMPJmD08/S1FwVkphmNI/AAAAAAAAABg/xfgkMQzPAGo/s72-c/Activation.PNG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8436642170609457318.post-7809145166193203342</id><published>2009-07-11T17:58:00.033+02:00</published><updated>2010-01-19T11:44:41.809+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='WiX'/><category scheme='http://www.blogger.com/atom/ns#' term='TeamBuild'/><title type='text'>Injecting a version number into WiX via TeamBuild</title><content type='html'>I have found several ways of injecting a version number into Wix via TeamBuild, but most of them require way too much work. After a few days of experimenting I ended up with this solution.

My TFSBuild.proj file contains the Major and Minor versions and a target "GenerateBuildNumber" to generate build and revision numbers. I use these to create a 'Versionnumber' property and add that to the &amp;lt;custompropertiesforbuild&amp;gt; property.

&lt;pre class="xml" name="code"&gt;
&amp;lt;propertygroup&amp;gt;
  &amp;lt;assemblymajorversion&amp;gt;2&amp;lt;/assemblymajorversion&amp;gt;
  &amp;lt;assemblyminorversion&amp;gt;7&amp;lt;/assemblyminorversion&amp;gt;
  &amp;lt;custompropertiesforbuild&amp;gt;
    SignAssembly=true;DelaySign=false;AssemblyOriginatorKeyFile=$(PrivateKeyLocation)
  &amp;lt;/custompropertiesforbuild&amp;gt;
&amp;lt;/propertygroup&amp;gt;

&amp;lt;target name="BuildNumberOverrideTarget" dependsontargets="GenerateBuildNumber"&amp;gt;
  &amp;lt;createproperty value="$(AssemblyMajorVersion).$(AssemblyMinorVersion).$(GeneratedBuildNumber).$(GeneratedRevisionNumber)"&amp;gt;
    &amp;lt;output taskparameter="Value" propertyname="Versionnumber" /&amp;gt;
  &amp;lt;/createproperty&amp;gt;

  &amp;lt;!-- Add the dynamically generated Versionnumber to the custom build properties for use in the WIX project --&amp;gt;
  &amp;lt;createproperty value="$(CustomPropertiesForBuild);Versionnumber=$(Versionnumber)"&amp;gt;
    &amp;lt;output taskparameter="Value" propertyname="CustomPropertiesForBuild" /&amp;gt;
  &amp;lt;/createproperty&amp;gt;
&amp;lt;/target&amp;gt;
&lt;/pre&gt;
For setting the version number in a WiX project, you need to get the value in the Product.wxs file. My predecessor had defined PRODUCTVERSION to contain a placeholder value "_versionnumber_".
Note: The official way would have been to use the &amp;lt;defineconstants&amp;gt; in the WiX project file but in my case, other builds were already depending on the placeholder so I didn't want to change this.
&lt;pre class="xml" name="code"&gt;
&amp;lt;?define PRODUCTVERSION="_versionnumber_"?&amp;gt;
&lt;/pre&gt;
In my WiX project file I have overriden the "BeforeBuild" target to replace the "_versionnumber_" placeholder with the actual value of $(Versionnumber). I'm using the 'File.Replace' task from the &lt;a href="http://www.codeplex.com/sdctasks/"&gt;SDC Tasks library&lt;/a&gt;.
&lt;pre class="xml" name="code"&gt;
&amp;lt;Target name="BeforeBuild"&amp;gt;
     &amp;lt;microsoft.sdc.tasks.file.replace
       Path="Product.wxs"
       OldValue="%22_versionnumber_%22"
       NewValue="%22$(Versionnumber)%22"
       Force="true"
       IgnoreCase="true"&amp;gt;
   &amp;lt;/Target&amp;gt;
&lt;/pre&gt;
As a final step, I have overriden the "AfterBuild" target of the WiX project to rename the output msi in order to contain the versionnumber in the filename as well.
&lt;pre class="xml" name="code"&gt;
&amp;lt;Target name="AfterBuild"&amp;gt;  
 &amp;lt;Createproperty value="$(TargetDir)%(CultureGroup.OutputFolder)"&amp;gt;  
   &amp;lt;Output taskparameter="Value" propertyname="TargetDir"&amp;gt;  
 &amp;lt;/CreateProperty&amp;gt;  
 
 &amp;lt;Copy sourcefiles="$(TargetDir)$(TargetName)$(TargetExt)"  
       destinationfiles="$(TargetDir)$(TargetName).$(Versionnumber)$(TargetExt)"&amp;gt;  
   
 &amp;lt;Delete files="$(TargetDir)$(TargetName)$(TargetExt)"&amp;gt;  
&amp;lt;/Target&amp;gt;
&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8436642170609457318-7809145166193203342?l=bartjolling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bartjolling.blogspot.com/feeds/7809145166193203342/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8436642170609457318&amp;postID=7809145166193203342' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/7809145166193203342'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/7809145166193203342'/><link rel='alternate' type='text/html' href='http://bartjolling.blogspot.com/2009/07/injecting-version-number-into-wix-via.html' title='Injecting a version number into WiX via TeamBuild'/><author><name>Bart</name><uri>http://www.blogger.com/profile/01531240801317106633</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8436642170609457318.post-7566756150312914980</id><published>2008-11-24T15:10:00.019+01:00</published><updated>2008-11-25T09:51:00.631+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='C++/CLI'/><category scheme='http://www.blogger.com/atom/ns#' term='Controls'/><category scheme='http://www.blogger.com/atom/ns#' term='MFC'/><title type='text'>Making MFC controls available for WinForms through MFC subclassing</title><content type='html'>&lt;p&gt;When trying to figure out how to use some of my MFC controls in a WinForms application, I came across this &lt;a href="http://www.codeproject.com/KB/miscctrl/mfcandwindowsforms.aspx"&gt;article&lt;/a&gt; by &lt;a href="http://www.codeproject.com/script/Articles/MemberArticles.aspx?amid=15383"&gt;Rama Krishna Vavilala&lt;/a&gt;. As his article was targetting the .NET 1.1 framework, I decided to rework it for .NET 2.0. The main difference is the switch from using Managed Extension for C++ to using C++/CLI.&lt;/p&gt;&lt;h3&gt;Static Win32 library for C3DMeterCtrl&lt;/h3&gt;
&lt;p&gt;As is the case in Rama's article, I will also use Mark C. Malburg's &lt;a href="http://www.codeproject.com/KB/miscctrl/3dmeter.aspx"&gt;Analog Meter Control&lt;/a&gt;. So first, create a Win32 static library project with support for MFC and precompiled headers called "ControlS" (S stands for static). This will contain the MFC code for the existing 3DMeterCtrl control. Place the files 3DMeterCtrl.cpp, 3DMeterCtrl.h and MemDC.h in the "ControlS" project. Modify the 3DMeterCtrl.cpp file to remove the line &lt;span style="color: rgb(51, 51, 255);"&gt;#include&lt;/span&gt; "MeterTestForm.h".
&lt;/p&gt;&lt;p&gt;The .NET designer and runtime will call functions that try to talk to your MFC control even before its window handle is created. In case of the C3DMeterCtrl, I needed to add this function call at the beginning of the "UpdateNeedle" and "ReconstructControl" functions:&lt;/p&gt;
&lt;pre name="code" class="c++"&gt;
if (!GetSafeHwnd())
return;
&lt;/pre&gt;
&lt;h3&gt;MFC library for the managed 'ThreeDMeter' control&lt;/h3&gt;
&lt;p&gt;To bridge the gap between MFC and .NET I'm going to use C++/CLI. This allows me to create a managed wrapper object around the MFC control.
&lt;/p&gt;&lt;p&gt;Add an "MFC DLL" project, called "control". Go to the project properties and enable the common language runtime support (/clr). Using the "Add Class" wizard add a new control and call it "ThreeDMeter". Make these changes to the ThreeDMeter.h file:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;#include&lt;/span&gt; the header file of the MFC control "..\ControlS\3DMeterCtrl.h"&lt;/li&gt;&lt;li&gt;Change the inheritance of the control to &lt;span style="color: rgb(51, 51, 255);"&gt;public&lt;/span&gt; System::Windows::Forms::Control&lt;/li&gt;&lt;li&gt;Add a private instance of C3DMeterCtrl to the class. Create it in the constructor and delete it in the finalizer. In "OnHandleCreated", call its "SubclassWindow" method using the .NET controls window handle.
&lt;/li&gt;&lt;/ul&gt;The file "ThreeDMeter.h" should now look like this:
&lt;pre name="code" class="c++"&gt;
#pragma once

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

#include "..\ControlS\3DMeterCtrl.h"

namespace Control {

public ref class ThreeDMeter : public System::Windows::Forms::Control
{
public:
ThreeDMeter(void)
{
  InitializeComponent();
  m_pCtrl = new C3DMeterCtrl();
}

protected:
//Finalizer
!ThreeDMeter()
{
  if (m_pCtrl != NULL)
  {
    delete m_pCtrl;
    m_pCtrl = NULL;
  }
}

//Destructor
~ThreeDMeter()
{
  if (components)
  {
    delete components;
  }

  //call finalizer to release unmanaged resources.
  this-&gt;!ThreeDMeter();
}

virtual void OnHandleCreated(EventArgs^ e) override
{
  System::Diagnostics::Debug::Assert(m_pCtrl-&gt;GetSafeHwnd() == NULL);

  m_pCtrl-&gt;SubclassWindow((HWND)Handle.ToPointer());

  Control::OnHandleCreated(e);
}

private:
System::ComponentModel::Container ^components;
C3DMeterCtrl* m_pCtrl;
};
&lt;/pre&gt;
In order to expose the properties of the MFC control in .NET, you need to implement them yourself. Add following code in the &lt;span style="color: rgb(51, 51, 255);"&gt;public&lt;/span&gt; section of the ThreeDMeter wrapper class.
&lt;pre name="code" class="c++"&gt;
event EventHandler^ OnValueChanged;

[property: System::ComponentModel::CategoryAttribute("Meter")]
property Color NeedleColor
{
  Color get()
  {
    if( m_pCtrl == NULL )
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()-&gt;ToString());
  
    return System::Drawing::ColorTranslator::FromWin32(m_pCtrl-&gt;m_colorNeedle);
  }
  
  void set(Color clr)
  {
    if (!m_pCtrl)
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()-&gt;ToString());
  
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
  
    m_pCtrl-&gt;SetNeedleColor(ColorTranslator::ToWin32(clr));
  }
}

[property: System::ComponentModel::CategoryAttribute("Meter")]
property String^ Units
{
  void set(String^ units)
  {
    if (!m_pCtrl)
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()-&gt;ToString());
  
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
  
    CString strUnits(units);
  
    m_pCtrl-&gt;SetUnits(strUnits);
  }
  
  String^ get()
  {
    if (!m_pCtrl)
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()-&gt;ToString());
  
    LPCTSTR szUnits = (m_pCtrl-&gt;m_strUnits);
  
    return gcnew String(szUnits);
  }
}

[property: System::ComponentModel::CategoryAttribute("Meter")]
property double Value
{
  double get()
  {
    if (!m_pCtrl)
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()-&gt;ToString());
  
    return m_pCtrl-&gt;m_dCurrentValue;
  }
  
  void set(double d)
  {
    if (!m_pCtrl)
      throw gcnew ObjectDisposedException(ThreeDMeter::GetType()-&gt;ToString());
  
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
  
    m_pCtrl-&gt;UpdateNeedle(d);
  
    OnValueChanged(this, EventArgs::Empty);
  }
}
&lt;/pre&gt;
&lt;h3&gt;.NET Test application&lt;/h3&gt;
In order to test the managed ThreeDMeter control, add a .NET "Windows application" project to the solution in your favorite language. Put the Three3Meter control on the form and add a timer control
&lt;pre name="code" class="vb"&gt;
Public Class Form1
  Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As system.EventArgs) Handles Timer1.Tick

    If Me.ThreeDMeter1.Value &lt;= 4 Then
      Me.ThreeDMeter1.Value += (Me.Timer1.Interval / 1000)
    Else
      Me.ThreeDMeter1.Value = -5
    End If
  End Sub
End Class
&lt;/pre&gt;
&lt;p&gt;This will make the meter move from left to right.&lt;/P&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8436642170609457318-7566756150312914980?l=bartjolling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bartjolling.blogspot.com/feeds/7566756150312914980/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8436642170609457318&amp;postID=7566756150312914980' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/7566756150312914980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/7566756150312914980'/><link rel='alternate' type='text/html' href='http://bartjolling.blogspot.com/2008/11/developing-windows-forms-control-using.html' title='Making MFC controls available for WinForms through MFC subclassing'/><author><name>Bart</name><uri>http://www.blogger.com/profile/01531240801317106633</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8436642170609457318.post-554889094265618705</id><published>2008-11-19T13:39:00.027+01:00</published><updated>2008-11-19T15:44:02.274+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Deleting absent, updating existing and inserting new rows in a table</title><content type='html'>&lt;p&gt;
Synchronizing a table based on a flat files is one of the more common tasks when dealing with databases. It should be a straight forward task to delete removed records, update changed records and insert new records but I often encounter horrible ways of achieving this goal.
&lt;/p&gt;&lt;p&gt;
I recently came across an implementation using a DTS package with a data-driven task in SQL Server 2000. For each line in the file it would launch several queries to detect if it was a new, updated or unchanged record (all glued together with VBScript) and then launch the appropriate query to update the database.
&lt;/p&gt;&lt;p&gt;Searching a bit on the internet I came across &lt;a href="http://blogs.meetandplay.com/WPierce/archive/2006/12/22/Delete_Absent_RowsUpdate_Existing_RowsInsert_New_Rows.aspx"&gt;this simple solution&lt;/a&gt;. The best way of doing this fast and reliably is by using the JOIN and LEFT JOIN clauses in your UPDATE, INSERT and DELETE commands to determine the status of the record. I would like to show my implementation of slightly more complicated requirements.
&lt;/p&gt;
&lt;H3&gt;Preparation&lt;/H3&gt;
&lt;p&gt;
First start by bulk inserting your data file into a staging table that has no constraints or indexes. This is the fastest way to get your data into the database. For the synchronisation queries (see below), you might want to consider using transactions if there is a risk of data corruption. You could also gain some speed by disabling the indexes while running the insert query.
&lt;BR/&gt;&lt;br/&gt;
In the following examples I will try to synchronize the &lt;span style="font-style:italic;"&gt;accounts&lt;/span&gt; table using the &lt;span style="font-style:italic;"&gt;tmp_accounts&lt;/span&gt; table as the staging table.

&lt;/p&gt;&lt;H3&gt;
Deleting removed rows
&lt;/H3&gt;
&lt;pre name="code" class="sql"&gt;
DELETE accounts 
FROM accounts acc LEFT JOIN tmp_accounts tmp
ON  acc.category = tmp.category
AND acc.code     = tmp.code
WHERE acc.code IS NULL
   OR acc.category IS NULL
&lt;/pre&gt;
&lt;p&gt;
Fields &lt;span style="font-style:italic;"&gt;code&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;category&lt;/span&gt; together uniquely define an account.&lt;br/&gt;
Using the LEFT JOIN with the FROM clause will ensure that all records from the &lt;span style="font-style:italic;"&gt;accounts&lt;/span&gt; table are selected, even if they don't exist in &lt;span style="font-style:italic;"&gt;tmp_accounts&lt;/span&gt;. The records that don't exist in &lt;span style="font-style:italic;"&gt;tmp_accounts&lt;/span&gt; will have a NULL value for every field. So all records that exist in the &lt;span style="font-style:italic;"&gt;accounts&lt;/span&gt; table but have NULL values in their &lt;span style="font-style:italic;"&gt;tmp_accounts&lt;/span&gt; fields, need to be deleted.
&lt;/p&gt;&lt;H3&gt;
Updating changed rows
&lt;/H3&gt;
&lt;pre name="code" class="sql"&gt;
UPDATE accounts SET
  description = tmp.description,
  type        = tmp.type,
  section     = tmp.section,
  audit_date  = tmp.audit_date,
  audit_user  = tmp.audit_user
FROM accounts     acc
JOIN tmp_accounts tmp
ON  acc.category = tmp.category
AND acc.code     = tmp.code
WHERE acc.description &lt;&gt; tmp.description
   OR acc.type        &lt;&gt; tmp.type
   OR acc.section     &lt;&gt; tmp.section
&lt;/pre&gt;
&lt;p&gt;
By using the JOIN clause, we are sure to work only on records that exist in both the &lt;span style="font-style:italic;"&gt;accounts&lt;/span&gt; table and the &lt;span style="font-style:italic;"&gt;tmp_accounts&lt;/span&gt; table.&lt;br/&gt;
Accounts need to be update in case their description, type or section has changed. Audit_user and audit_date are automatically filled in the &lt;span style="font-style:italic;"&gt;tmp_accounts&lt;/span&gt; table using a DEFAULT and are always kept up-to-date in the &lt;span style="font-style:italic;"&gt;accounts&lt;/span&gt; table.
&lt;/p&gt;&lt;H3&gt;
Inserting new rows
&lt;/H3&gt;
&lt;pre name="code" class="sql"&gt;
INSERT INTO accounts
( category,
  code,
  description, 
  type,
  section,
  title_only, 
  division,
  override,
  allow_manual_entry, 
  audit_date, 
  audit_user
)
SELECT
  tmp.category,
  tmp.code, 
  tmp.description,
  tmp.type,
  tmp.section,
  tmp.title_only, 
  tmp.division,
  tmp.override,
  tmp.allow_manual_entry, 
  tmp.audit_date,
  tmp.audit_user
FROM tmp_accounts  tmp
LEFT JOIN accounts acc
ON  tmp.category = acc.category
AND tmp.code     = acc.code
WHERE acc.code IS NULL
   OR acc.category IS NULL
&lt;/pre&gt;
&lt;p&gt;
Using a LEFT JOIN makes sure we are working with all records in the &lt;span style="font-style:italic;"&gt;tmp_accounts&lt;/span&gt; table, even if they don't exist in the &lt;span style="font-style:italic;"&gt;accounts&lt;/span&gt; table. Records that don't exist in the &lt;span style="font-style:italic;"&gt;accounts&lt;/span&gt; table will have NULL values for all of their fields. So all records that exist in &lt;span style="font-style:italic;"&gt;tmp_accounts&lt;/span&gt; and have NULL values for the &lt;span style="font-style:italic;"&gt;accounts&lt;/span&gt; fields, have to be inserted.
&lt;br/&gt;&lt;br/&gt;
Audit_user and audit_date are automatically filled in the &lt;span style="font-style:italic;"&gt;tmp_accounts&lt;/span&gt; table using a DEFAULT and are always kept up-to-date in the &lt;span style="font-style:italic;"&gt;accounts&lt;/span&gt; table
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8436642170609457318-554889094265618705?l=bartjolling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bartjolling.blogspot.com/feeds/554889094265618705/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8436642170609457318&amp;postID=554889094265618705' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/554889094265618705'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/554889094265618705'/><link rel='alternate' type='text/html' href='http://bartjolling.blogspot.com/2008/11/deleting-absent-updating-existing-and.html' title='Deleting absent, updating existing and inserting new rows in a table'/><author><name>Bart</name><uri>http://www.blogger.com/profile/01531240801317106633</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8436642170609457318.post-2522578132424591588</id><published>2008-09-05T17:22:00.011+02:00</published><updated>2008-11-19T15:44:23.514+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SMO'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Scripting with SQL Server Management Objects</title><content type='html'>&lt;p&gt;When I needed to move about 28500 stored procedures from a SQL Server 2000 to a SQL Server 2005, I turned to the SQL Server Management Studio. It didn't offer any option to move the stored procedures but it did allow to script them to a text file. I launched the "Generate Scripts" task and noticed that after 8 hours of processing only 3500 stored procedures had been scripted. The process had also eaten all the RAM on my workstation.
&lt;/p&gt;&lt;p&gt;
It would takes ages at this rate so I cancelled the task and turned to the &lt;a href="http://msdn.microsoft.com/en-us/library/ms162169.aspx"&gt;SQL Server Management Objects&lt;/a&gt; that are installed together with SQL Server Management Studio. According to MSDN, &lt;span style="font-style: italic;"&gt;SQL Server Management Objects (SMO) is a collection of objects that are designed for programming all aspects of managing Microsoft SQL Server&lt;/span&gt;.
&lt;/p&gt;&lt;p&gt;
The following code shows the C# application that I wrote to quickly generate scripts for all stored procedures in one database. In order to make it compile, you will need to add reference to the assemblies:
&lt;ul&gt;&lt;li&gt;Microsoft.SqlServer.Smo&lt;/li&gt;&lt;li&gt;Microsoft.SqlServer.SmoEnum&lt;/li&gt;&lt;li&gt;Microsoft.SqlServer.ConnectionInfo&lt;/li&gt;&lt;/ul&gt;What the application does in general, is:
&lt;ul&gt;&lt;li&gt; connect to the database&lt;/li&gt;&lt;li&gt;loops over the collection of all stored procedures&lt;/li&gt;&lt;li&gt;script it to a text file, if it is not a system stored procedure
&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;pre name="code" class="c-sharp"&gt;
using System;
using System.IO;
using System.Text;
using System.Collections.Specialized;

using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;

namespace SProcScripter
{
  class Program
  {
    static void Main(string[] args)
    {
        int success = 0;
        int failure = 0;

        StreamWriter sw = new StreamWriter("d:\\SProcs.sql");

        // Connect to server and database
        Server srv = new Server("myServerName");
        Database db = srv.Databases["myDatabaseName"];
        Scripter scrp = new Scripter(srv);

        scrp.Options.ScriptDrops = false;
        scrp.Options.WithDependencies = false;

        foreach (StoredProcedure sp in db.StoredProcedures)
        {
            try
            {
                Urn[] smoObjects;
                smoObjects = new Urn[1];
                smoObjects[0] = sp.Urn;

                if (!sp.IsSystemObject)
                {
                    Console.Write("Scripting " + sp.Name);

                    StringCollection sc = scrp.Script(smoObjects);
                    StringBuilder sb = new StringBuilder();

                    foreach (String st in sc)
                    {
                        sb.AppendLine(st);
                        sb.AppendLine("GO");
                    }

                    sw.WriteLine(sb.ToString());

                    success++;
                    Console.WriteLine(" done.");
                }
            }
            catch (Exception ex)
            {
                failure++;
                Console.WriteLine(" failed with exception: " + ex.Message);
            } // try - catch
        } // foreach stored procedure

        sw.Close();

        Console.WriteLine("Success: " + success.ToString());
        Console.WriteLine("Failure: " + failure.ToString());
        Console.WriteLine("Press any key");
        Console.ReadKey();

    } // void Main
  }
}
&lt;/pre&gt;
&lt;p&gt;
All stored procedures were generated within 30 minutes! I've tried to make this work faster using a ThreadPool but the SMO components are not thread-safe and all sort of unexpected errors and race conditions popped up. I needed to introduce several locks to keep the object out of each others way. I succeeded in making it work but due to these locks it wasn't really faster than the single threaded version above.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8436642170609457318-2522578132424591588?l=bartjolling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bartjolling.blogspot.com/feeds/2522578132424591588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8436642170609457318&amp;postID=2522578132424591588' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/2522578132424591588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/2522578132424591588'/><link rel='alternate' type='text/html' href='http://bartjolling.blogspot.com/2008/09/scripting-with-sql-server-management.html' title='Scripting with SQL Server Management Objects'/><author><name>Bart</name><uri>http://www.blogger.com/profile/01531240801317106633</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8436642170609457318.post-2623204778067765039</id><published>2008-09-04T00:44:00.007+02:00</published><updated>2010-01-19T11:48:24.299+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DTS'/><category scheme='http://www.blogger.com/atom/ns#' term='Designer'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Stand-Alone DTS Designer on SQL Server 2005</title><content type='html'>&lt;p&gt;&lt;em&gt;This article describes how to open the DTS Designer for SQL Server 2005 programmatically. It eliminates the need to open the SQL Server Management Studio if you just need to edit a DTS that was saved as a structured storage file. I’m building a command line utility in C# that takes the full path to a dts package as a parameter and opens it in the designer. You can find its &lt;a href="http://bart.jolling.googlepages.com/dtsdesigner80.vb"&gt;VB.NET code here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;In my previous post, I already created a similar utility in VB.NET that opened the DTS Designer on PC's with SQL Server Enterprise Manager installed, which is the client application for SQL Server 2000. The source code is exactly the same. The only differences are that you'll need to install the &lt;a href="http://download.microsoft.com/download/f/7/4/f74cbdb1-87e2-4794-9186-e3ad6bd54b41/SQLServer2005_DTS.msi" target="_blank"&gt;DTS Designer Components&lt;/a&gt; from the &lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=df0ba5aa-b4bd-4705-aa0a-b477ba72a9cb" target="_blank"&gt;Feature Pack for Microsoft SQL Server 2005&lt;/a&gt; and that your project will reference the Microsoft.SQLServer.Dts80.dll assembly from the GAC&lt;/p&gt;&lt;p&gt;Visual Studio 2005 doesn't allow you to reference this assembly directly from the GAC. If you would browse to the GAC's folder (by default in the &lt;span style="font-family:courier new;"&gt;%windir%\assembly&lt;/span&gt; folder), the Assembly Cache Viewer (SHFusion.dll) shell extension will be actived which doesn't have an option to copy assemblies. You could &lt;a href="http://www.codeproject.com/KB/dotnet/demystifygac.aspx" target="_blank"&gt;disable this shell extension&lt;/a&gt; but it is just as easy to copy the assembly to a diffent filder using the command prompt:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Click Start &lt;/li&gt;&lt;li&gt;Click Run... &lt;/li&gt;&lt;li&gt;Type 'cmd.exe' and press &amp;lt;enter&amp;gt;. The command prompt appears &lt;/li&gt;&lt;li&gt;Type the following command: &lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;span style="font-family:courier new;"&gt;copy %windir%\assembly\GAC_MSIL\Microsoft.SqlServer.Dts80\9.0.242.0__89845dcd8080cc91\Microsoft.SqlServer.Dts80.dll c:\data\&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This will put a copy of the Microsoft.SqlServer.Dts80.dll to c:\data\ from where you can reference it in Visual Studio 2005. As soon as the project is finished and compiles you don't need this file anymore as your executable will use the one in the GAC.&lt;/p&gt;&lt;p&gt;In order to get started, open Visual Studio and create a new Windows application in C#. Put a reference to the Microsoft.SqlServer.Dts80.dll that you have copied to c:\data\&lt;/p&gt;&lt;p&gt;Create a ShowPkgDesigner function that takes the full pathname of an existing DTS package:&lt;/p&gt;
&lt;pre name="code" class="c-sharp"&gt;
private static void ShowPkgDesigner(string sPackagePathName)
{
  DTS.CDTSLegacyDesigner designer = null;
  String packageName = String.Empty;
  String packageID = String.Empty;
  String packageVersionID = String.Empty;

  //* Remove quotes from packagePath
  sPackagePathName = sPackagePathName.Replace("\"", "");

  if (sPackagePathName == String.Empty ||
      ShowPkgBrowser(ref packageName, ref packageID,
                     ref packageVersionID, sPackagePathName))
{
  try
  {
    designer = new DTS.CDTSLegacyDesigner();

    designer.Initialize();
    designer.Location = 2;
    designer.PackageID = packageID;
    designer.PackageName = packageName;
    designer.ServerName = sPackagePathName;
    designer.VersionID = packageVersionID;

    //* Launch designer
    designer.ShowDesigner();
  }
  finally
  {
    if (designer != null)
    {
      designer.Dispose();
      designer = null;
    }
  }
}
}
&lt;/pre&gt;
&lt;p&gt;Multiple DTS packages and versions can be safed in one structured storage file. The ShowPckBrowser function allows a user to select a specific version of a DTS package:&lt;/p&gt;&lt;pre name="code" class="c-sharp"&gt;
private static bool ShowPkgBrowser(ref String sPackageName,
                                  ref String sPackageID,
                                  ref String sPackageVersionID,
                                  String sPackagePathName)
{
 DTS.Package package = null;
 DTS.SavedPackageInfos packageInfoColl = null;
 DTS.SavedPackageInfo packageInfo = null;

 int selectedPackage = 0;

 package = new DTS.Package();
 packageInfoColl = package.GetSavedPackageInfos(sPackagePathName);

 if (packageInfoColl.Count == 1)
   selectedPackage = 1;
 else
 {
   PackageBrowser pckBrowser = new PackageBrowser();
  
   for (int i = 1; i &amp;lt;= packageInfoColl.Count; i++)
   {
     packageInfo = packageInfoColl.Item(i);
     pckBrowser.AddPackageVersion(
     packageInfo.VersionSaveDate.ToString(),
     packageInfo.PackageName);
   }
  
   if (pckBrowser.ShowDialog() == DialogResult.OK)
     selectedPackage = pckBrowser.SelectedPackage;
 }
  
 if (selectedPackage &amp;gt; 0)
 {
   packageInfo = packageInfoColl.Item(selectedPackage);
   sPackageName = packageInfo.PackageName;
   sPackageID = packageInfo.PackageID;
   sPackageVersionID = packageInfo.VersionID;
  
   return true;
 }
 else
 {
   return false;
 }
}&lt;/pre&gt;
&lt;p&gt;The code above use a custom form that only contains a listbox. In the for loop, all versions and DTS package are added to that listbox. As soon as a user double-clicks on the desired version, the 'PackageBrowser.SelectedPackage' contains the index of that version. This is then used to retrieve the package name, id and versionId. I'll leave it up to the reader to implement the PackageBrowser component.&lt;/p&gt;&lt;p&gt;All that's left to do is to call the ShowPkgDesigner function from the main function. I want my executable to take the full path to the DTS package so that I can link it to "*.dts" files in Windows Explorers' "Open With..." functionality:&lt;/p&gt;&lt;pre name="code" class="c-sharp"&gt;
static int Main(string[] args)
{
  try
  {
    String packagePath = String.Empty;
    
    // Full path to the DTS package is the first command line option
    if (args.Length &amp;gt; 0)
    {
      if ((new System.IO.FileInfo(args[0])).Exists)
        packagePath = args[0];
      else
      {
        OpenFileDialog openFiledlg = new OpenFileDialog();
        
        openFiledlg.CheckFileExists = true;
        openFiledlg.Filter =
        "DTS Packages(*.dts)*.dtsAll Files(*.*)*.*";
        
        if (openFiledlg.ShowDialog() == DialogResult.OK)
        packagePath = openFiledlg.FileName;
      }
    }
    
    ShowPkgDesigner(packagePath);
    
    return 0;
  }
  
  catch (Exception ex)
  {
    MessageBox.Show(ex.Message, "DTSDesigner90 Error",
    MessageBoxButtons.OK, MessageBoxIcon.Error);
    return -1;
  }
}&lt;/PRE&gt;
&lt;p&gt;If no path is provided to the command line, an empty designer sheet is opened. If an invalid pathname is passed, the user will be prompted to browse to an existing file.&lt;/p&gt;&lt;p&gt;Having this command line utility has really improved my productivity when I was constantly editing and comparing DTS packages that were scattered all over the companies network. Being able to open a package by just double-clicking it is just that little bit more efficient than opening them through the SQL Server Management Studio.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8436642170609457318-2623204778067765039?l=bartjolling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bartjolling.blogspot.com/feeds/2623204778067765039/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8436642170609457318&amp;postID=2623204778067765039' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/2623204778067765039'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/2623204778067765039'/><link rel='alternate' type='text/html' href='http://bartjolling.blogspot.com/2008/09/stand-alone-dts-designer-on-sql-server.html' title='Stand-Alone DTS Designer on SQL Server 2005'/><author><name>Bart</name><uri>http://www.blogger.com/profile/01531240801317106633</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8436642170609457318.post-385226479523242764</id><published>2008-08-13T21:25:00.001+02:00</published><updated>2008-11-19T15:44:56.299+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='DTS'/><category scheme='http://www.blogger.com/atom/ns#' term='Designer'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server'/><title type='text'>Stand-Alone DTS Designer on SQL Server 2000</title><content type='html'>&lt;p&gt;&lt;em&gt;This article describes how to open the DTS Designer for SQL Server 2000 programmatically. It eliminates the need to open the SQL Server Enterprise Manager if you just need to edit a DTS that was saved as a structured storage file. In this article I'm building a command line utility in VB.NET that takes the full path to a dts package as a parameter and opens it in the designer. You can find its &lt;a href="http://bart.jolling.googlepages.com/dtsdesigner80.vb" target="_blank"&gt;VB.NET code here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;I recently started working on a project involving the creation and modification of DTS packages that were scattered around on many different systems and file shares. What really annoyed me was the fact that you are forced to go via the SQL Server Enterprise Manager and connect to a random SQL Server, even if you wanted to open a DTS package that was saved to the file system as a structured storage file.&lt;/p&gt;  &lt;p&gt;After some searching on the internet for a DTS API, I came across the MSDN article on &lt;a href="http://msdn.microsoft.com/en-us/library/aa176227%28SQL.80%29.aspx" target="_blank"&gt;Creating DTS Packages in Visual Basic&lt;/a&gt;. No explanation however was given on how to open the designer programmatically although the library (dtspck.dll) included an object called &lt;strong&gt;CDTSLegacyDesigner&lt;/strong&gt;, which clearly was the object I was after.&lt;/p&gt;  &lt;p&gt;The following VB.NET code shows how to load the designer with a empty design surface. You will have to add a reference to the COM component dtspck.dll first, which is installed together with the SQL Server 2000 Client Tools (such as Enterprise Manager, Query Analyzer...)&lt;/p&gt;  &lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;   &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;     &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;   designer = &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; DTS.CDTSLegacyDesigner&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;   designer.Initialize()&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;   designer.ShowDesigner()&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Finally&lt;/span&gt;     &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Not&lt;/span&gt; designer &lt;span style="color: #0000ff"&gt;Is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     designer.Dispose()&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     Marshal.ReleaseComObject(designer)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     designer = &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;If&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt; &lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;DTS packages are &lt;a href="http://msdn.microsoft.com/en-us/library/aa933547%28SQL.80%29.aspx" target="_blank"&gt;saved as a structured storage file&lt;/a&gt;. A single file can contain multiple DTS packages and multiple package versions. The following simplified code shows how to retrieve the necessary information about last package version stored in the DTS. You should loop over the &lt;em&gt;packageInfoColl&lt;/em&gt; collection and allow users to select the version they wish to open.&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; sPackageName &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; sPackageID &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; sPackageVersionID &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; sPackagePathName &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; &lt;span style="color: #0000ff"&gt;String&lt;/span&gt; &lt;span style="color: #008000"&gt;'Full pathname to DTS package   &lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;    &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; package &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; DTS.Package = &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; packageInfoColl &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; DTS.SavedPackageInfos = &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;Dim&lt;/span&gt; packageInfo &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; DTS.SavedPackageInfo = &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;   package = &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; DTS.Package &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;   packageInfoColl = package.GetSavedPackageInfos(sPackagePathName) &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;   &lt;span style="color: #008000"&gt;'** Example: select the last saved version &lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;   packageInfo = packageInfoColl.Item(packageInfoColl.Count) &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt;   sPackageName = packageInfo.PackageName &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;   sPackageID = packageInfo.PackageID &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;   sPackageVersionID = packageInfo.VersionID&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Finally&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Not&lt;/span&gt; package &lt;span style="color: #0000ff"&gt;Is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt; Marshal.ReleaseComObject(package) &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Not&lt;/span&gt; packageInfo &lt;span style="color: #0000ff"&gt;Is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt; Marshal.ReleaseComObject(packageInfo) &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  22:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Not&lt;/span&gt; packageInfoColl &lt;span style="color: #0000ff"&gt;Is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt; Marshal.ReleaseComObject(packageInfoColl) &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  23:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; Try&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;When you have retrieved the packageName, packageID and packageVersion you can pass these as properties to your instance of the CDTSLegacyDesigner class as shown in the following code. The &lt;em&gt;location&lt;/em&gt; property indicates that the DTS package should be loaded from the file system.&lt;/p&gt;

&lt;div style="border-right: gray 1px solid; padding-right: 4px; border-top: gray 1px solid; padding-left: 4px; font-size: 8pt; padding-bottom: 4px; margin: 20px 0px 10px; overflow: auto; border-left: gray 1px solid; width: 97.5%; cursor: text; max-height: 200px; line-height: 12pt; padding-top: 4px; border-bottom: gray 1px solid; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; background-color: #f4f4f4"&gt;
  &lt;div style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;
    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   1:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   2:&lt;/span&gt;   designer = &lt;span style="color: #0000ff"&gt;New&lt;/span&gt; DTS.CDTSLegacyDesigner&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   3:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;With&lt;/span&gt; designer&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   4:&lt;/span&gt;     .Initialize()&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   5:&lt;/span&gt;     .Location = 2&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   6:&lt;/span&gt;     .PackageID = packageID&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   7:&lt;/span&gt;     .PackageName = packageName&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   8:&lt;/span&gt;     .ServerName = packagePathName&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;   9:&lt;/span&gt;     .VersionID = packageVersionID&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  10:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;With&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  11:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  12:&lt;/span&gt;   &lt;span style="color: #008000"&gt;'** Launch designer&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  13:&lt;/span&gt;   designer.ShowDesigner()&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  14:&lt;/span&gt;&amp;#160; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  15:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Finally&lt;/span&gt;  &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  16:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;If&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Not&lt;/span&gt; designer &lt;span style="color: #0000ff"&gt;Is&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Then&lt;/span&gt;    &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  17:&lt;/span&gt;     designer.Dispose()&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  18:&lt;/span&gt;     Marshal.ReleaseComObject(designer)&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  19:&lt;/span&gt;     designer = &lt;span style="color: #0000ff"&gt;Nothing&lt;/span&gt; &lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  20:&lt;/span&gt;   &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;If&lt;/span&gt;&lt;/pre&gt;

    &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: white; border-bottom-style: none"&gt;&lt;span style="color: #606060"&gt;  21:&lt;/span&gt; &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; Try&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Putting these code snippets together into a function application still takes some work but you can find my try on &lt;a href="http://bart.jolling.googlepages.com/dtsdesigner80.vb" target="_blank"&gt;my googlepage&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8436642170609457318-385226479523242764?l=bartjolling.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bartjolling.blogspot.com/feeds/385226479523242764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8436642170609457318&amp;postID=385226479523242764' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/385226479523242764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8436642170609457318/posts/default/385226479523242764'/><link rel='alternate' type='text/html' href='http://bartjolling.blogspot.com/2008/08/stand-alone-dts-designer-on-sql-server.html' title='Stand-Alone DTS Designer on SQL Server 2000'/><author><name>Bart</name><uri>http://www.blogger.com/profile/01531240801317106633</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
