<?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-6581636505340878377</id><updated>2011-04-21T11:07:20.640-07:00</updated><category term='VSA'/><category term='Visual Basic .Net'/><category term='blogger'/><category term='SQL Command'/><category term='javascript'/><category term='FTP Task'/><category term='stored procedure'/><category term='reporting services'/><category term='CLR hosted assembly'/><category term='clock'/><category term='Precompiling'/><category term='html'/><category term='user controls'/><category term='asp.net'/><category term='Script Task'/><category term='viewstate'/><category term='http'/><category term='SSIS'/><title type='text'>On.The.Learning.Curve</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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>10</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6581636505340878377.post-2626354260393212947</id><published>2008-04-16T20:52:00.000-07:00</published><updated>2008-04-16T20:54:01.097-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='reporting services'/><category scheme='http://www.blogger.com/atom/ns#' term='CLR hosted assembly'/><category scheme='http://www.blogger.com/atom/ns#' term='stored procedure'/><title type='text'>Calling CLR Hosted Stored Procedure from Reporting Services</title><content type='html'>&lt;p class="MsoNormal"&gt;In short, you can’t. And this is with SQL Server 2005 SP2. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;!--[if !supportEmptyParas]--&gt; &lt;!--[endif]--&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-weight: bold;" class="MsoNormal"&gt;Problem:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;1. I created a CLR hosted assembly stored procedure called HostedSProc using a VS2005 database project.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;2. I deployed the project and it created a stored procedure called ‘dbo.HostedSProc’ on the server. Well and good.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;3. I tested calling the sproc from SQL Management Studio and it worked fine.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;4. I then created a VS2005 Report Project and set the data source of my report to call a stored procedure ‘dbo.HostedSProc’. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;5. When I tried to run it, it returned ‘stored procedure ‘dbo.HostedSProc’ could not be found.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;!--[if !supportEmptyParas]--&gt; &lt;!--[endif]--&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p style="font-weight: bold;" class="MsoNormal"&gt;Solution:&lt;/p&gt;  &lt;p class="MsoNormal"&gt;1. Create a ‘normal’ stored procedure that ‘wraps’ the call to the hosted stored procedure.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;2. I created a stored procedure called ‘HostedSProcWrapper’ and in the stored procedure I call the ‘HostedSProc’ procedure. See below.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;3. The wrapper should have the same signature as the internally called procedure, so you can assign parameters from report designer. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;4. I tried it and it works. &lt;/p&gt;  &lt;p class="MsoNormal"&gt;5. What I especially like is that even though you’ve called a ‘wrapper’ stored proc, the Report Designer can still detect the fields returned by the internal stored proc, to be used in the reports.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;!--[if !supportEmptyParas]--&gt; &lt;!--[endif]--&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;CREATE&lt;/span&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt; &lt;span style="color: blue;"&gt;PROCEDURE&lt;/span&gt; [dbo]&lt;span style="color: gray;"&gt;.&lt;/span&gt;[HostedSProcWrapper] &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: green;"&gt;-- Add the parameters (or more) of the stored proc we’ll call here&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;      &lt;/span&gt;@docId &lt;span style="color: blue;"&gt;varchar&lt;/span&gt;&lt;span style="color: gray;"&gt;(&lt;/span&gt;100&lt;span style="color: gray;"&gt;)&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;AS&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;BEGIN&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;SET&lt;/span&gt; &lt;span style="color: blue;"&gt;NOCOUNT&lt;/span&gt; &lt;span style="color: blue;"&gt;ON&lt;/span&gt;&lt;span style="color: gray;"&gt;;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: gray;"&gt;&lt;!--[if !supportEmptyParas]--&gt; &lt;!--[endif]--&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;    &lt;/span&gt;&lt;span style="color: green;"&gt;-- Call the stored proc here, passing in the required params.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;  &lt;p class="MsoNormal" style=""&gt;&lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;;"&gt;&lt;span style=""&gt;      &lt;/span&gt;&lt;span style="color: blue;"&gt;exec&lt;/span&gt; dbo.HostedSProc @docId&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/p&gt;  &lt;span style="font-size: 10pt; font-family: &amp;quot;Courier New&amp;quot;; color: blue;"&gt;END&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6581636505340878377-2626354260393212947?l=onthelearningcurve.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/2626354260393212947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6581636505340878377&amp;postID=2626354260393212947' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/2626354260393212947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/2626354260393212947'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/2008/04/calling-clr-hosted-stored-procedure.html' title='Calling CLR Hosted Stored Procedure from Reporting Services'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6581636505340878377.post-4574291754897489918</id><published>2008-03-25T02:39:00.000-07:00</published><updated>2008-03-25T03:02:17.495-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Precompiling'/><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><category scheme='http://www.blogger.com/atom/ns#' term='Script Task'/><title type='text'>Script Task Precompiling bahaviour , custom references and side by side execution</title><content type='html'>If you have a script task that references a custom assembly, you would know by now that the custom assembly needs be in the GAC. However the GAC copy is only used during runtime.&lt;br /&gt;&lt;br /&gt;For development, you'll also need to have the custom reference in the Microsoft.Net framework directory, ex &lt;span style="color: rgb(51, 102, 255);"&gt;C:\Windows\Microsoft.Net\Framework\v2.0.50727\&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Now what if you have two versions of the SSIS package, and two versions of the custom assembly, and these need to be developed and executed side by side. How do we handle this? See below for some notes:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Development&lt;/span&gt;&lt;br /&gt;1. Make sure the correct version of the custom assembly you want your SSIS Script Task/Component to work with is in the .net framework directory. What I mean is, if you're working on v1.0 of your SSIS package, and the script tasks are supposed to reference v1.0 of your custom assembly, make sure v1.0 of the custom assembly is in the .net framework directory.&lt;br /&gt;&lt;br /&gt;If are working with v1.0 SSIS package, you have v1.1 of the custom assembly in .net framework directory, and you open the script task, it will automatically pick up the framework directory version and if you have turned on precompiling, it will compile against the v1.1, and during runtime, will look for that version in GAC. The same works vice versa.&lt;br /&gt;&lt;br /&gt;2. When you're done with v1.0 SSIS package, and start work on v1.1, copy the v1.1 of the custom assembly to the .net framework directory first, before opening your package, and especially before opening your script tasks.&lt;br /&gt;&lt;br /&gt;Set a post build event on your custom assembly's project to automatically copy the built assembly to GAC AND copy to your .net framework directory. This ensures you're always developing your SSIS package against the correct custom assembly.&lt;br /&gt;Example post build event:&lt;br /&gt;&lt;blockquote&gt;"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" /if "$(TargetPath)"&lt;br /&gt;copy /Y "$(TargetPath)" "C:\Windows\Microsoft.Net\Framework\v2.0.50727\$(TargetFileName)"&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Runtime&lt;/span&gt;&lt;br /&gt;1. If precompiling is turned off, the custom assembly has to be placed in the .net framework directory the SSIS Script task will compile at runtime, against the version in .net framework directory.&lt;br /&gt;&lt;br /&gt;2. If you have v1.0 and v1.1 SSIS packages deployed on a machine, and v1.1 of custom assembly is in the .net framework dir, and their script tasks are not precompiled, BOTH SSIS packages will compile against v1.1 of your custom assembly. If your v1.1 custom assembly is not backward compatible with v1.0, your v1.0 SSIS package could break at runtime.&lt;br /&gt;&lt;br /&gt;Turning on precompiling eliminates the need to have the custom assembly in the framework directory, and multiple versions of SSIS packages can run simultaneously.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6581636505340878377-4574291754897489918?l=onthelearningcurve.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/4574291754897489918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6581636505340878377&amp;postID=4574291754897489918' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/4574291754897489918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/4574291754897489918'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/2008/03/script-task-precompiling-bahaviour.html' title='Script Task Precompiling bahaviour , custom references and side by side execution'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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-6581636505340878377.post-5715837440216686010</id><published>2008-03-25T02:31:00.001-07:00</published><updated>2008-03-25T02:38:20.604-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Visual Basic .Net'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Command'/><title type='text'>Getting constraint columns from a SQL Command</title><content type='html'>Sorry i don't have the solution. Does anyone know what is a good and clean way to extract the columns specified in the WHERE clause in a SQL Command? &lt;br /&gt;eg, SQL COmmand :&lt;br /&gt;&lt;blockquote&gt;SELECT * FROM HELLOWORLD WHERE FNAME='JOHN' AND LNAME='DOE' &lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I want to be able to extract the texts 'FNAME' and 'LNAME'. Working with vb.net. &lt;br /&gt;&lt;br /&gt;Ideas?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6581636505340878377-5715837440216686010?l=onthelearningcurve.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/5715837440216686010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6581636505340878377&amp;postID=5715837440216686010' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/5715837440216686010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/5715837440216686010'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/2008/03/getting-constraint-columns-from-sql.html' title='Getting constraint columns from a SQL Command'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6581636505340878377.post-4425284835151820459</id><published>2008-03-21T07:50:00.000-07:00</published><updated>2008-03-21T08:03:06.539-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='VSA'/><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><title type='text'>SSIS Script task Precompiling fails, even though code has no errors</title><content type='html'>Have you ever written a beautiful piece of VB.Net code in your Script Task, but it just refuses to precompile? It happened to me. &lt;br /&gt;&lt;br /&gt;It happened after I installed a patch for .Net framework 2.0, and then those silly script tasks just won't precompile no matter what.&lt;br /&gt;&lt;br /&gt;Turns out the framework patch updated something to do with VSA (Visual Studio for Applications) engine, the same thing SSIS uses for Script Tasks. This would only happen on installations of SQL Server 2005, SQL Server 2005 SP1. &lt;br /&gt;&lt;br /&gt;Updating to SP2 fixes this. &lt;br /&gt;&lt;br /&gt;See here for more details: &lt;br /&gt;http://support.microsoft.com/kb/932557&lt;br /&gt;http://support.microsoft.com/kb/931846&lt;br /&gt;&lt;br /&gt;Hope this eases some pain.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6581636505340878377-4425284835151820459?l=onthelearningcurve.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/4425284835151820459/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6581636505340878377&amp;postID=4425284835151820459' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/4425284835151820459'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/4425284835151820459'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/2008/03/ssis-script-task-precompiling-fails.html' title='SSIS Script task Precompiling fails, even though code has no errors'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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-6581636505340878377.post-2322777351343206913</id><published>2008-02-10T18:20:00.000-08:00</published><updated>2008-02-10T18:45:43.458-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><category scheme='http://www.blogger.com/atom/ns#' term='FTP Task'/><title type='text'>SSIS FTP Task Password (and other) Problems</title><content type='html'>Originally posted on SQL Server Central, but posting it here as well for my future reference. :) &lt;br /&gt;&lt;br /&gt;I've had some problems with the SSIS FTP Task where it does not seem to make the connections correctly. I keep getting the error "Password is invalid" and all sorts of errors. &lt;br /&gt;&lt;br /&gt;I don't really like to use the script task component because of it just creates another area of potential coding error in the project. &lt;br /&gt;&lt;br /&gt;But I had to take control of the FTP task functionality myself in order to make it do what I wanted it to do.&lt;br /&gt;&lt;br /&gt;I realised that when the FTP Task does a listing, the unix box returns not only the file name but the timestamp as well. &lt;br /&gt;Eg, &lt;br /&gt;&lt;b&gt;Problem 1&lt;/b&gt;&lt;br /&gt;directory on the unix box&lt;br /&gt;/files&lt;br /&gt;  File1.trg&lt;br /&gt;  File2.trg&lt;br /&gt;&lt;br /&gt;When listing from FTP Task: remote directory = /files&lt;br /&gt;"10:00 File1.trg"&lt;br /&gt;"12:00 File2.trg"&lt;br /&gt;&lt;br /&gt;Now, when the ftp task tries to get these files, its not found, or throws some error. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Problem 2&lt;/b&gt;&lt;br /&gt;Passwords. Using a batch file to script the FTP is not a good solution, because at the end of the day, your password is clearly visible in plaintext in the script. Not a good solution. Using the package configuration file (*.dtsConfig) is useless as it too stores passwords in plaintext (till now, ssis hasn't implemented encrypted configuration files). Don't even think of using enterprise library with SSIS, you'll run into major headaches.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Solution&lt;/b&gt;&lt;br /&gt;I've since given up on using the FTP task for my FTP, but we can still use SSIS's FTP plumbing and with some extra coding, make a properly platform independent and secure FTP function. &lt;br /&gt;&lt;br /&gt;I've removed the error checking and variable assignment to make things easier to read.&lt;br /&gt;Steps:&lt;br /&gt;1. Create a FTP Connection Manager in your SSIS Designer 'RightClick in Connections - New Connection... - FTP'. &lt;br /&gt;2. Create a variable to store the password.&lt;br /&gt;Setup the package to use configuration file to store the password variable (and other information you need).&lt;br /&gt;3. Fill in the FTP information as needed. 3. &lt;br /&gt;4. Write a simple .net application that does string encryption. I won't put code for this here. You can google how to do this easily.&lt;br /&gt;5. Use this tool to navigate the xpath of the dtsConfig file to password variable's value and encrypt it. This way, the password is not plaintext on the dtsconfig file.&lt;br /&gt;6. Create a script task to take the password variable's (as readwrite) value and 'decrypt' it, remember to use whatever method was used to encrypt it in your separate .net app. Assign the decrypted password back to itself.&lt;br /&gt;6. Create a script task to do the FTP functionality.&lt;br /&gt;&lt;code&gt; Public Sub Main()&lt;br /&gt;       'TODO: assign variables here...&lt;br /&gt;           dim password as string = dts.variables("vPassword").value.tostring 'the decrypted password&lt;br /&gt;&lt;br /&gt;           'Get instance of the connection manager.&lt;br /&gt;            Dim cm As ConnectionManager = Dts.Connections("FTPConnMgr")&lt;br /&gt;            'Set the password property to the decrypted password&lt;br /&gt;            cm.Properties("ServerPassword").SetValue(cm, password)&lt;br /&gt;&lt;br /&gt;            'create the FTP object that sends the files and pass it the connection created above.&lt;br /&gt;            Dim ftp As FtpClientConnection = New FtpClientConnection(cm.AcquireConnection(Nothing))&lt;br /&gt;&lt;br /&gt;            'Connect to the ftp server&lt;br /&gt;             ftp.Connect()&lt;br /&gt;&lt;br /&gt;             ftp.SetWorkingDirectory(remoteDir) 'set the remote directory&lt;br /&gt; &lt;br /&gt;            Dim files(0) As String&lt;br /&gt;            files(0) = fileToGet 'eg. File1.trg&lt;br /&gt;&lt;br /&gt;            'Get the file&lt;br /&gt;            ftp.ReceiveFiles(files, localDir, True, True)&lt;br /&gt;&lt;br /&gt;            ' Close the ftp connection&lt;br /&gt;            ftp.Close()&lt;br /&gt;&lt;br /&gt;       &lt;br /&gt;        Dts.Events.FireInformation(0, context, "File " + fileToGet + " retrieved successfully.", Nothing, Nothing, True)&lt;br /&gt;        Dts.TaskResult = Dts.Results.Success&lt;br /&gt;&lt;br /&gt;    End Sub&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So there you go. An ssis package that decrypts a encrypted password on a dtsconfig file, decrypts it at runtime, and doesn't use batch files that expose the password.&lt;br /&gt;&lt;br /&gt;If you'd like to know how to do a batch get of all files in a directory, i can show in another post. Whenever you need to change the password, just use that separate .net app to modify the dtsconfig file. Nothing needs to be done on the package.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6581636505340878377-2322777351343206913?l=onthelearningcurve.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/2322777351343206913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6581636505340878377&amp;postID=2322777351343206913' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/2322777351343206913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/2322777351343206913'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/2008/02/ssis-ftp-task-password-and-other.html' title='SSIS FTP Task Password (and other) Problems'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6581636505340878377.post-1771127634802792417</id><published>2007-03-28T02:08:00.000-07:00</published><updated>2007-03-28T02:18:13.782-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSIS'/><title type='text'>Dynamically modifying an SSIS 2005 package</title><content type='html'>&lt;p&gt;There may be a time when you need to create a package with a data flow that needs to be modified at run-time. This means that at design time, you don't create any column mappings, or maybe a few standard columns like a 'CreateDate' or 'UpdateDate' columns, but the actual data columns are not known at design time.&lt;/p&gt;&lt;p&gt;This requirement creates some problems like:&lt;br /&gt;1. SQL Server doesn't have the necessary columns to store the data.&lt;br /&gt;2. To create columns in SQL, we need the data type and length (if applies) for each column.&lt;br /&gt;3. SSIS 2005 user scripts can't be used to modify the SSIS in which it is contained.&lt;br /&gt;and a couple of more issues that i can't remember anymore... haha...&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Well one approach will be to write an application/service that will:&lt;br /&gt;1. Update SQL table with new/modified tables&lt;br /&gt;2. Load the package and create sql table mappings.&lt;br /&gt;3. Execute the package, if required.&lt;br /&gt;&lt;/p&gt;&lt;p align="left"&gt;We'll take a look at each of these steps in more detail.&lt;br /&gt;&lt;strong&gt;1. Update SQL table with new/modified tables&lt;br /&gt;1.1&lt;/strong&gt; To update SQL table, we need a the column definitions ie column name, datatype, length. This can be obtained from the source table and written to a csv file or read directly from the source database's INFORMATION_SCHEMA.COLUMNS view. Here's a sample code:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color:#3333ff;"&gt;select&lt;/span&gt; COLUMN_NAME, DATA_TYPE, NUMERIC_PRECISION, NUMERIC_SCALE &lt;span style="color:#3333ff;"&gt;from&lt;/span&gt; INFORMATION_SCHEMA.COLUMNS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color:#3333ff;"&gt;where&lt;/span&gt; TABLE_NAME = 'Client'&lt;/span&gt;&lt;br /&gt;Note: if you're integrating data between different databases eg. UniVerse -&gt; SQL, Oracle -&gt; SQL, SQL -&gt; Oracle, etc..., you may need a function that will 'map' the different datatype between the database types.&lt;/p&gt;&lt;p align="left"&gt;&lt;br /&gt;&lt;strong&gt;1.2&lt;/strong&gt; Once you have the column definitions, you can make the connection to the SQL database (I'm assuming its sql, you can do it with other databases as well) and create your database table's columns.&lt;br /&gt;Note: You need to import the following namespace in your application to be able to do the database manipulation:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Microsoft.SqlServer.Management.Smo()&lt;br /&gt;Microsoft.SqlServer.Management.Common()&lt;br /&gt;&lt;/span&gt;Code example to acquire a connection to the database in your program:&lt;/p&gt;&lt;p align="left"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim db As Microsoft.SqlServer.Management.Smo.Database&lt;br /&gt;'Get connection settings&lt;br /&gt;Dim DBServerName, DBUser, DBPassword, DBName As String&lt;br /&gt;DBServerName = "MyServer"&lt;br /&gt;DBUser = "sa"&lt;br /&gt;DBPassword = "sa_password"&lt;br /&gt;DBName = "MyDatabase"&lt;br /&gt;Dim SrvConn As New Microsoft.SqlServer.Management.Common.ServerConnection(DBServerName)&lt;br /&gt;SrvConn.LoginSecure = False&lt;br /&gt;SrvConn.Login = DBUser&lt;br /&gt;SrvConn.Password = DBPassword&lt;br /&gt;Dim srv As New Server(SrvConn)&lt;br /&gt;'Open Required Database&lt;br /&gt;db = srv.Databases(MyDatabase)&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:courier new;"&gt;&lt;p align="left"&gt;&lt;br /&gt;&lt;/span&gt;To get to the table you want to edit, use the &lt;span style="font-family:courier new;"&gt;db.Tables&lt;/span&gt;(tableName as string) function&lt;/p&gt;&lt;p align="left"&gt;&lt;br /&gt;&lt;strong&gt;1.3&lt;/strong&gt; Write code to add the columns&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim tb As Table = db.Tables(tableName)&lt;br /&gt;Dim newDataType As SqlDataType&lt;br /&gt;newDataType = DataType.VarChar(intDataTypeLength)&lt;br /&gt;Dim newColumn As New Column(tableName, columnName, newDataType)&lt;br /&gt;tb.Columns.Add(newColumn)&lt;br /&gt;&lt;/span&gt;Your SQL table is now ready for mapping.&lt;/p&gt;&lt;p align="left"&gt;&lt;br /&gt;&lt;strong&gt;2. Now the more difficult part.&lt;br /&gt;&lt;/strong&gt;Import the following namespaces:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Microsoft.SqlServer.Dts.Runtime.Wrapper&lt;br /&gt;Microsoft.SqlServer.Dts.Runtime&lt;br /&gt;Microsoft.SqlServer.Dts.Pipeline.Wrapper&lt;/span&gt;&lt;/p&gt;&lt;p align="left"&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;2.1 Load the package (i'm assuming its on filesystem)&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim app As New Microsoft.SqlServer.Dts.Runtime.Application&lt;br /&gt;Dim pkg As Microsoft.SqlServer.Dts.Runtime.Package&lt;br /&gt;pkg = app.LoadPackage("C:\PackageToEdit.dtsx", Nothing)&lt;/span&gt;&lt;/p&gt;&lt;span style="font-family:courier new;"&gt;&lt;p align="left"&gt;&lt;br /&gt;&lt;/span&gt;2.2 Now that you have loaded the package, we now need to 'navigate' to the component that is the dataflow component for the table you're going to modify.&lt;br /&gt;To modify a dataflow, we have to start updating the names from the 'top' of the flow and end at the 'bottom' of the flow. This is what's called as the 'pipeline' by Microsoft.&lt;br /&gt;Here's a basic sequence of modification we'll make.&lt;br /&gt;a. Update the source connection manager with column names&lt;br /&gt;b. Update the data flow source component&lt;br /&gt;c. Update the data flow destination component&lt;br /&gt;We'll go into detail now...&lt;/p&gt;&lt;p align="left"&gt;&lt;br /&gt;&lt;strong&gt;2.2.a&lt;/strong&gt; Load the source connection manager.&lt;br /&gt;You should know the name of your connection manager during design time. Its always good to use a naming convention for your components so they can be parameter driven if necessary.&lt;br /&gt;What you need at this stage:&lt;br /&gt;i) a variable / array containing the column names to be updated&lt;br /&gt;ii) the source connection manager name as used in the SSIS Designer&lt;br /&gt;iii) the package variable (we already loaded earlier)&lt;br /&gt;Steps:&lt;br /&gt;i. Get the connection manager object from the list of package's connection managers. I'm using an example of a flat file connection manager.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim SrcConn As ConnectionManager = Nothing&lt;br /&gt;'Get specific connection&lt;br /&gt;SrcConn = pkg.Connections.Item(ConnectionName)&lt;br /&gt;'Get the underlying connection object&lt;br /&gt;Dim FlatConnMgr As Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerFlatFile90&lt;br /&gt;FlatConnMgr = CType(SrcConn.InnerObject, Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerFlatFile90)&lt;br /&gt;ii. Now we create a new column and add to the connection manager's columns collection&lt;br /&gt;Dim NewCol As RTW.IDTSConnectionManagerFlatFileColumn90 = nothing&lt;br /&gt;FlatConnMgr.Columns.Add(NewCol)&lt;br /&gt;'Assign the new column's properties&lt;br /&gt;NewCol.ColumnType = "Delimited"&lt;br /&gt;NewCol.ColumnDelimiter = "~"&lt;br /&gt;NewCol.ColumnWidth = 1&lt;br /&gt;NewCol.DataType = Wrapper.DataType.DT_STR&lt;br /&gt;NewCol.MaximumWidth = 1&lt;br /&gt;NewCol.DataScale = 0&lt;br /&gt;NewCol.DataPrecision = 0&lt;br /&gt;name = CType(NewCol, RTW.IDTSName90)&lt;br /&gt;name.Name = &lt;mycolumnname&gt;&lt;br /&gt;name.Description = &lt;mycolumnname&gt;&lt;br /&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style="color:#ff0000;"&gt;NOTE&lt;/span&gt;&lt;/strong&gt; : &lt;strong&gt;Data type incompatibility&lt;/strong&gt;. Looks easy? Here's a problem. &lt;/p&gt;&lt;p align="left"&gt;SSIS datatypes and SQL data types are NOT the same. You need to do some 'mapping' between the SSIS data type and SQL datatype. We already know what the column's SQL data type is, because we used it to create the SQL column, remember? So we just need to have a function that can do some 'mapping' for us. For your convenience, i'll include what i use, and you can modify if necessary.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Public Function MapSQLtoSSISDataType(ByVal SQLDT As SqlDataType) As Dts.Runtime.DataType&lt;br /&gt;Select Case SQLDT.SqlDataType&lt;br /&gt;Case SqlDataType.BigInt&lt;br /&gt;Return Wrapper.DataType.DT_I8&lt;br /&gt;Case SqlDataType.Binary&lt;br /&gt;Return Wrapper.DataType.DT_BYTES&lt;br /&gt;Case SqlDataType.Bit&lt;br /&gt;Return Wrapper.DataType.DT_BOOL&lt;br /&gt;Case SqlDataType.Char&lt;br /&gt;Return Wrapper.DataType.DT_STR&lt;br /&gt;Case SqlDataType.DateTime&lt;br /&gt;Return Wrapper.DataType.DT_DBTIMESTAMP&lt;br /&gt;Case SqlDataType.Decimal&lt;br /&gt;Return Wrapper.DataType.DT_DECIMAL&lt;br /&gt;Case SqlDataType.Float&lt;br /&gt;Return Wrapper.DataType.DT_NUMERIC&lt;br /&gt;Case SqlDataType.Image&lt;br /&gt;Return Wrapper.DataType.DT_BYTES&lt;br /&gt;Case SqlDataType.Int&lt;br /&gt;Return Wrapper.DataType.DT_I4&lt;br /&gt;Case SqlDataType.Money&lt;br /&gt;Return Wrapper.DataType.DT_CY&lt;br /&gt;Case SqlDataType.NChar&lt;br /&gt;Return Wrapper.DataType.DT_WSTR&lt;br /&gt;Case SqlDataType.None&lt;br /&gt;Return Wrapper.DataType.DT_STR&lt;br /&gt;Case SqlDataType.NText&lt;br /&gt;Return Wrapper.DataType.DT_NTEXT&lt;br /&gt;Case SqlDataType.NVarChar&lt;br /&gt;Return Wrapper.DataType.DT_STR&lt;br /&gt;Case SqlDataType.NVarCharMax&lt;br /&gt;Return Wrapper.DataType.DT_STR&lt;br /&gt;Case SqlDataType.Real&lt;br /&gt;Return Wrapper.DataType.DT_DECIMAL&lt;br /&gt;Case SqlDataType.SmallDateTime&lt;br /&gt;Return Wrapper.DataType.DT_DBTIMESTAMP&lt;br /&gt;Case SqlDataType.SmallInt&lt;br /&gt;Return Wrapper.DataType.DT_I2&lt;br /&gt;Case SqlDataType.SmallMoney&lt;br /&gt;Return Wrapper.DataType.DT_CY&lt;br /&gt;Case SqlDataType.SysName&lt;br /&gt;Return Wrapper.DataType.DT_STR&lt;br /&gt;Case SqlDataType.Text&lt;br /&gt;Return Wrapper.DataType.DT_TEXT&lt;br /&gt;Case SqlDataType.Timestamp&lt;br /&gt;Return Wrapper.DataType.DT_DBTIME&lt;br /&gt;Case SqlDataType.UniqueIdentifier&lt;br /&gt;Return Wrapper.DataType.DT_GUID&lt;br /&gt;Case SqlDataType.VarChar&lt;br /&gt;Return Wrapper.DataType.DT_STR&lt;br /&gt;Case SqlDataType.VarCharMax&lt;br /&gt;Return Wrapper.DataType.DT_STR&lt;br /&gt;Case SqlDataType.Xml&lt;br /&gt;Return Wrapper.DataType.DT_STR&lt;br /&gt;Case Else&lt;br /&gt;Return Wrapper.DataType.DT_STR&lt;br /&gt;End Select&lt;br /&gt;End Function&lt;br /&gt;&lt;/span&gt;You can use this function to return the appropriate SSIS data type from the SQL data type you have on the database. Not perfect but you can use it as a base.&lt;/p&gt;&lt;p align="left"&gt;&lt;br /&gt;iii. Once you've done the above for all your new columns, your Source Connection Manager will now have the necessary columns to be accessed downstream in the data flow.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2.2.b&lt;/strong&gt; &lt;strong&gt;Update the Data Flow Components&lt;/strong&gt;&lt;br /&gt;Information you need at this point:&lt;br /&gt;i) The name of the data flow component to update&lt;br /&gt;ii) All the names of the data flow components you want to update as used in the SSIS Designer.&lt;br /&gt;iii) list of new columns to add.&lt;br /&gt;Steps:&lt;br /&gt;&lt;strong&gt;i)&lt;/strong&gt; Get the data flow component object.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim DataFlowTaskHost As TaskHost&lt;br /&gt;Dim DataFlowMainPipe As MainPipe&lt;br /&gt;DataFlowTaskHost = CType(pkg.Executables(&lt;dataflowtaskname&gt;), TaskHost)&lt;br /&gt;DataFlowMainPipe = CType(DataFlowTaskHost.InnerObject, MainPipe)&lt;br /&gt;&lt;/span&gt;We now have the main pipeline of the data flow (whatever you see in the 'Data Flow' in the SSIS designer)&lt;/p&gt;&lt;p align="left"&gt;&lt;br /&gt;&lt;strong&gt;ii)&lt;/strong&gt; Now get the &lt;strong&gt;data SOURCE&lt;/strong&gt; object (top of the data flow). I'm assuming this data source component is set up to use the data source connection manager we already updated.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim DFSource As IDTSComponentMetaData90&lt;br /&gt;DFSource = DataFlowMainPipe.ComponentMetaDataCollection.Item(SourceComponentName)&lt;br /&gt;'Create an Instance of the source component&lt;br /&gt;Dim instDfSource As CManagedComponentWrapper = DFSource.Instantiate&lt;br /&gt;Now we 're-assign' the connection manager for this component so that it retrieves the new values that was updated on the connection manager earlier.&lt;br /&gt;DFSource.RuntimeConnectionCollection(0).ConnectionManagerID = pkg.Connections.Item(&lt;connectionmanagername&gt;).ID&lt;br /&gt;DFSource.RuntimeConnectionCollection(0).ConnectionManager = DtsConvert.ToConnectionManager90(pkg.Connections(SourceComponentConnectionMgrName))&lt;br /&gt;instDfSource.AcquireConnections(Nothing)&lt;br /&gt;instDfSource.ReinitializeMetaData()&lt;br /&gt;instDfSource.ReleaseConnections()&lt;br /&gt;&lt;/span&gt;Note: the reinitalizeMetaData step is very important as it updates the internal/external metadata to be seen by other components.&lt;/p&gt;&lt;p align="left"&gt;&lt;br /&gt;&lt;strong&gt;iii)&lt;/strong&gt; Now we need to update the &lt;strong&gt;data DESTINATION&lt;/strong&gt; object. In this example, i'm assuming its an OLEDB Insert object.&lt;br /&gt;As for the source component, we need to get hold of the component's object&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim cmDestination As IDTSComponentMetaData90&lt;br /&gt;cmDestination = DataFlowMainPipe.ComponentMetaDataCollection.Item(DataFlow Insert Dest. Name)&lt;br /&gt;Dim instDFDest As CManagedComponentWrapper = cmDestination.Instantiate&lt;/span&gt;&lt;br /&gt;Reassign the connection manager&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;cmDestination.RuntimeConnectionCollection(0).ConnectionManagerID = pkg.Connections.Item(DestinationComponent ConnectionManager Name).ID&lt;br /&gt;cmDestination.RuntimeConnectionCollection(0).ConnectionManager = DtsConvert.ToConnectionManager90(pkg.Connections(DestinationComponent ConnectionManager Name))&lt;br /&gt;instDFDest.AcquireConnections(Nothing)&lt;br /&gt;instDFDest.ReinitializeMetaData()&lt;br /&gt;&lt;/span&gt;Get the input object of the component so that we can add the new columns.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Dim input As IDTSInput90 = cmDestination.InputCollection(0)&lt;br /&gt;Dim vInput As IDTSVirtualInput90 = input.GetVirtualInput()&lt;br /&gt;&lt;/span&gt;We need to map each column of the input object's to the external metadata columns of the 'upstream' component, which is our source. This will make the Insert component aware of the new columns.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;For Each vColumn As IDTSVirtualInputColumn90 In vInput.VirtualInputColumnCollection&lt;br /&gt;Dim vCol As IDTSInputColumn90 = instDFDest.SetUsageType(input.ID, vInput, vColumn.LineageID, DTSUsageType.UT_READWRITE)&lt;br /&gt;instDFDest.MapInputColumn(input.ID, vCol.ID, input.ExternalMetadataColumnCollection(vColumn.Name).ID)&lt;br /&gt;Next&lt;br /&gt;&lt;/span&gt;to finalise the changes we need to reinitialise the metadata.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;instDFDest.ReinitializeMetaData()&lt;br /&gt;instDFDest.ReleaseConnections()&lt;/span&gt;&lt;br /&gt;The 'ReinitialiseMetaData' will actually check the columns against the SQL table (using its assigned connection manager) and report any errors here.&lt;br /&gt;Done! you've got your components updated with the custom data.&lt;br /&gt;If you'd like to see the changes, save your package using the app.SaveToXml function and you can open it in the editor.&lt;br /&gt;This is a 'rough' guide and you'll need to add and fine tune it to your purposes.&lt;br /&gt;Let me know if you found it helpful.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6581636505340878377-1771127634802792417?l=onthelearningcurve.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/1771127634802792417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6581636505340878377&amp;postID=1771127634802792417' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/1771127634802792417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/1771127634802792417'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/2007/03/dynamically-modifying-ssis-2005-package.html' title='Dynamically modifying an SSIS 2005 package'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6581636505340878377.post-8960042092037500815</id><published>2007-03-14T02:03:00.000-07:00</published><updated>2007-03-14T02:05:28.159-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='http'/><title type='text'>What makes programming difficult?</title><content type='html'>... statements like this:&lt;br /&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style="font-family:trebuchet ms;"&gt;One &lt;em&gt;difference&lt;/em&gt; between HTTP handlers and ISAPI extensions is that HTTP&lt;br /&gt;handlers can be called directly by using their file name in the URL, &lt;em&gt;similar&lt;/em&gt; to&lt;br /&gt;ISAPI extensions&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;p&gt;haha!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6581636505340878377-8960042092037500815?l=onthelearningcurve.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/8960042092037500815/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6581636505340878377&amp;postID=8960042092037500815' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/8960042092037500815'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/8960042092037500815'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/2007/03/what-makes-programming-difficult.html' title='What makes programming difficult?'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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-6581636505340878377.post-7037947508758530589</id><published>2007-03-12T20:12:00.000-07:00</published><updated>2007-03-12T20:23:00.997-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blogger'/><category scheme='http://www.blogger.com/atom/ns#' term='html'/><title type='text'>Posting source code / html in Blogger</title><content type='html'>Bummer, i tried to post some source code in blogger and it went haywire. I thought it was as easy as cutting and pasting. but noo! it 'parsed' my html and tried to run my script and display my &amp;lt;form&amp;gt;.&lt;br /&gt;&lt;br /&gt;Well, the crucial step is to replace all the ampersands and 'greater/less than' signs to their html equivalent. It basically accomplished in three steps.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Change the &amp;amp; to "&amp; amp ;" (without the space) in your code snippet.&lt;/li&gt;&lt;li&gt;Change the "&lt;" to "&amp;amp; lt ;" (without the space)&lt;/li&gt;&lt;li&gt;Change the "&gt;" to "&amp;amp; gt;") (without the space)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Now cut and paste it into your blog editor.&lt;/p&gt;&lt;p&gt;Alternatively, head on &lt;a href="http://centricle.com/tools/html-entities/"&gt;Centricle &lt;/a&gt;and let their conversion tool do it for you. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6581636505340878377-7037947508758530589?l=onthelearningcurve.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/7037947508758530589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6581636505340878377&amp;postID=7037947508758530589' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/7037947508758530589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/7037947508758530589'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/2007/03/posting-source-code-html-in-blogger.html' title='Posting source code / html in Blogger'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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-6581636505340878377.post-299649204484661020</id><published>2007-03-12T19:27:00.000-07:00</published><updated>2007-03-12T23:53:54.082-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='user controls'/><category scheme='http://www.blogger.com/atom/ns#' term='clock'/><title type='text'>Javascript live clock</title><content type='html'>It came to pass, that I needed to display the time on a page (though i'm still wondering why because windows does that for you on the task bar). Obviously the solution would be javascript. Here's the code i used, maybe someone would find it useful.&lt;br /&gt;Description of what's happening is after the code.&lt;br /&gt;&lt;div class="code" id="liveclock"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;color:#3333ff;"&gt;&lt;span style="color:#000066;"&gt;&amp;lt;HTML&amp;gt;&lt;br /&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;br /&gt;setInterval("setTheTime()", 1000);&lt;br /&gt;&lt;br /&gt;function setTheTime () {&lt;br /&gt;var curtime = new Date();&lt;br /&gt;var curhour = curtime.getHours();&lt;br /&gt;var curmin = curtime.getMinutes();&lt;br /&gt;var cursec = curtime.getSeconds();&lt;br /&gt;var time = "";&lt;br /&gt;if(curhour == 0) curhour = 12;&lt;br /&gt;time = (curhour &amp;gt; 12 ? curhour - 12 : curhour) + ":" +&lt;br /&gt;(curmin &amp;lt; 10 ? "0" : "") + curmin + ":" +&lt;br /&gt;(cursec &amp;lt; 10 ? "0" : "") + cursec + " " +&lt;br /&gt;(curhour &amp;gt; 12 ? "PM" : "AM");&lt;br /&gt;document.date.clock.value = time;&lt;br /&gt;}&lt;br /&gt;&lt;span style="color:#330099;"&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;&amp;lt;form name="date"&amp;gt;&lt;br /&gt;&amp;lt;input type="text" name="clock" style="border: 0px" value=""&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt&lt;/span&gt;;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Explanation:&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#3333ff;"&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;setInterval("setTheTime()", 1000);&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:Courier New;font-size:85%;"&gt;&lt;/span&gt;&lt;br /&gt;Set interval is a function that performs a task after an interval (in milliseconds) specified. It basically starts a 'thread' that keeps looping. Go here for more info on &lt;a href="http://www.w3schools.com/htmldom/met_win_setinterval.asp"&gt;setInterval()&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;color:#3333ff;"&gt;function setTheTime()&lt;/span&gt;&lt;br /&gt;This function will calculate current time and update the necessary field / element on the page with the time.&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="font-family:courier new;color:#3333ff;"&gt;var curtime = new Date();&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;This returns an object that represents the current date &amp; time&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;color:#3333ff;"&gt;var curhour = curtime.getHours();&lt;br /&gt;var curmin = curtime.getMinutes();&lt;br /&gt;var cursec = curtime.getSeconds();&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;self explanatory, right?&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;color:#3333ff;"&gt;if(curhour == 0) curhour = 12;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;the time is represented in 24hrs format, this statement converts the 00 hrs (which is 12AM) to the number 12. If you want to keep in 24 hrs, remark or remove this line.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;&lt;span style="color:#3333ff;"&gt;time = (curhour &amp;gt; 12 ? curhour - 12 : curhour) + ":" +&lt;br /&gt;(curmin &amp;lt; 10 ? "0" : "") + curmin + ":" +&lt;br /&gt;(cursec &amp;lt; 10 ? "0" : "") + cursec + " " +&lt;br /&gt;(curhour &amp;gt; 12 ? "PM" : "AM");&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;This statement forms the string that will be displayed. we'll take a look at it line by line.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;color:#3333ff;"&gt;(curhour &amp;gt; 12 ? curhour - 12 : curhour)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;this is a conditional statement.&lt;br /&gt;if the hour in 24hr format is more than 12, it will return the 12hr format equivalent which is obtained by deducting 12 from it. otherwise it will return the same value.&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#3333ff;"&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;(curmin &amp;lt; 10 ? "0" : "") + curmin&lt;/span&gt; ;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;another conditional statement that returns a 0 to be prepended to the minute if its less that 10.&lt;br /&gt;ex. 9 will be returned as 09, 5 as 05 etc...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;"&gt;(&lt;span style="color:#3333ff;"&gt;cursec &amp;lt; 10 ? "0" : "") + cursec ;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;same as the minute.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;color:#3333ff;"&gt;(curhour &amp;gt; 12 ? "PM" : "AM")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;returns the AM or PM text based on the hour.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:85%;color:#3333ff;"&gt;document.date.clock.value = time;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;this is a straightforward statement that tells which object's value needs to be updated with the text.&lt;br /&gt;in more complex pages, like .aspx pages, you may need to update a textbox or label. use the following code&lt;br /&gt;Updating a textbox:&lt;br /&gt;&lt;span style="font-family:courier new;color:#3333ff;"&gt;document.all["&amp;lt;%=txtTime%&amp;gt;"].value = time&lt;/span&gt;&lt;br /&gt;Updating a label:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="color:#3333ff;"&gt;document.getElementById("&amp;lt;%=lblDateTime%&amp;gt;").innerText = time&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Note &lt;/span&gt;: I update the innerText property instead of the innerHtml because on some browsers, updating innerHtml repeatedly can cause a memory leak.&lt;br /&gt;&lt;br /&gt;This is all fine when your elements are all on the page.&lt;br /&gt;If the element you want to update is in a user control, it creates a different problem because the &lt;span style="color:#3333ff;"&gt;"&amp;lt;%=txtTime%&amp;gt;"&lt;/span&gt; or &lt;span style="color:#3333ff;"&gt;&amp;lt;%=lblDateTime%&amp;gt;&lt;/span&gt; will fail. You see, when a user control is registered, each control on each usercontrol (there can be more than one of the same user control on a page) rendered will be given a unique ID that we don't know at design time. So when the javascript tries to update the object, it can’t find it because there is no object with that ID and the time is not updated.&lt;br /&gt;To overcome this, we use another property of the element we want to update, which is called the .&lt;span style="font-family:courier new;"&gt;ClientID&lt;/span&gt; which is the unique ID of the control that has been rendered.&lt;br /&gt;&lt;br /&gt;So the new text should be&lt;br /&gt;textbox: &lt;span style="font-family:courier new;color:#3333ff;"&gt;document.all["&amp;lt;%=txtTime.ClientID%&amp;gt;"].value = time&lt;/span&gt;&lt;br /&gt;label : &lt;span style="font-family:courier new;color:#3333ff;"&gt;document.getElementById("&amp;lt;%=lblDateTime.ClientID%&amp;gt;").innerText = time&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As for myself, i just use the object.ClientID whether or not i'm using user controls to avoid any complication.&lt;br /&gt;&lt;br /&gt;Hope that helps.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6581636505340878377-299649204484661020?l=onthelearningcurve.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/299649204484661020/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6581636505340878377&amp;postID=299649204484661020' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/299649204484661020'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/299649204484661020'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/2007/03/javascript-live-clock.html' title='Javascript live clock'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6581636505340878377.post-7950515159214919254</id><published>2007-03-09T00:26:00.000-08:00</published><updated>2007-03-09T00:35:23.621-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='user controls'/><category scheme='http://www.blogger.com/atom/ns#' term='viewstate'/><category scheme='http://www.blogger.com/atom/ns#' term='asp.net'/><title type='text'>ViewState in user control / child user controls</title><content type='html'>So i have a page which loads a user control, call it ctrlA and ctrlA has a user control ctrlB, which is loaded at runtime when i click a button.&lt;br /&gt;I load my page, ctrlA is loaded and everythings looks good. i hit my button, and ctrlB is loaded. No problem.&lt;br /&gt;Now ctrlB also has a button, when i hit this, the page gives me an error saying "The cast is invalid". What in the world happened?!&lt;br /&gt;I found the problem.&lt;br /&gt;In ctrlA if have a property that reads viewstate("Mode").&lt;br /&gt;I also have the same property in ctrlB. So when the page hits a postback, and the 'LoadViewState' event fires, the page seems to go bonkers when it (i assume) tries to read the second viewstate("Mode") into memory.&lt;br /&gt;I renamed the viewstate variable to use a different name in ctrlB and everything went fine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6581636505340878377-7950515159214919254?l=onthelearningcurve.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://onthelearningcurve.blogspot.com/feeds/7950515159214919254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6581636505340878377&amp;postID=7950515159214919254' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/7950515159214919254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6581636505340878377/posts/default/7950515159214919254'/><link rel='alternate' type='text/html' href='http://onthelearningcurve.blogspot.com/2007/03/viewstate-in-user-control-child-user.html' title='ViewState in user control / child user controls'/><author><name>Guna</name><uri>http://www.blogger.com/profile/01662046230785625549</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>
