<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>.Net and C#</title><link>http://blogs.x2line.com/al/category/24.aspx</link><description>Posts specifically related to Microsoft .NET Framework and C#. Including runtime features and future versions of Framework, tools, configuration considerations and best practices. Also: c# specifications, design guidelines and best practices. Discussions regarding performance considerations, announcements, etc</description><managingEditor>Anatoly Lubarsky</managingEditor><dc:language>en-US</dc:language><generator>Version 0.97.2006.1</generator><image><url>http://images.x2line.com/logos/x2line_br_109.jpg</url><title>x2line - We Build Applications</title><link>http://blogs.x2line.com/</link></image><item><dc:creator>Anatoly Lubarsky</dc:creator><title>Running MSI on Windows 7</title><link>http://blogs.x2line.com/al/archive/2009/09/01/3699.aspx</link><pubDate>Tue, 01 Sep 2009 21:17:00 GMT</pubDate><guid>http://blogs.x2line.com/al/archive/2009/09/01/3699.aspx</guid><wfw:comment>http://blogs.x2line.com/al/comments/3699.aspx</wfw:comment><comments>http://blogs.x2line.com/al/archive/2009/09/01/3699.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.x2line.com/al/comments/commentRss/3699.aspx</wfw:commentRss><trackback:ping>http://blogs.x2line.com/al/services/trackbacks/3699.aspx</trackback:ping><description>&lt;p&gt;I didn't try Windows 7 yet. But seems that Windows 7 inherited user access control feature from Windows Vista as is. It maybe useful info for people running MSIs on Windows 7.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;I learned it because &lt;a href="http://lifehacker.com/5349236/turn-google-voice-into-a-growl+friendly-windows-app"&gt;lifehacker&lt;/a&gt; linked yesterday to my 2-year-old post about &lt;a href="http://blogs.x2line.com/al/archive/2007/07/20/3210.aspx"&gt;MSI Error 2869&lt;/a&gt; on Windows Vista where I explained the error and how to deal with it (lifehacker had the same MSI problem on Windows 7). In short &amp;mdash; the error is caused by user access control feature and you need to run MSI from command line as administrator as a workaround (or patch the MSI). I was a bit surprised yesterday while reading that 2-year-old post since it seems very techy and it took me a while to fully understand it :). Good coverage after all...&lt;/p&gt;</description></item><item><dc:creator>Anatoly Lubarsky</dc:creator><title>Render Text With Anti-alias Using TextRenderingHint (ClearTypeGridFit)</title><link>http://blogs.x2line.com/al/archive/2009/03/13/3644.aspx</link><pubDate>Fri, 13 Mar 2009 14:39:00 GMT</pubDate><guid>http://blogs.x2line.com/al/archive/2009/03/13/3644.aspx</guid><wfw:comment>http://blogs.x2line.com/al/comments/3644.aspx</wfw:comment><comments>http://blogs.x2line.com/al/archive/2009/03/13/3644.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.x2line.com/al/comments/commentRss/3644.aspx</wfw:commentRss><trackback:ping>http://blogs.x2line.com/al/services/trackbacks/3644.aspx</trackback:ping><description>&lt;p&gt;Let's suppose we have to draw a bitmap with a piece of text in C# using &lt;i&gt;System.Drawing&lt;/i&gt;. The text characters will not look very good and smooth by default. Enabling &lt;i&gt;ClearType&lt;/i&gt; in windows would have solved a problem but suppose we want to change nothing in windows.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;It can be a web server generating string bitmaps, so enabling ClearType would be counter-productive and take unnecessary resources from unrelated processes. Not to mention — the end user will see the lowest text quality despite ClearType settings on her computer because the bitmap is generated on the server with ClearType disabled.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Implementing &lt;i&gt;Graphics.TextRenderingHint&lt;/i&gt; property which specifies the quality of text rendering would solve the problem. &lt;i&gt;Graphics.TextRenderingHint&lt;/i&gt; utilizes one value from &lt;i&gt;TextRenderingHint enumeration&lt;/i&gt; for example &lt;b&gt;ClearTypeGridFit&lt;/b&gt; (which means — use ClearType). Example:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
grph.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
grph.DrawString(myString, myFont, myBrush, xPosition, yPosition);
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;TextRenderingHint enumeration values range from SystemDefault (fastest performance, but lowest quality) to ClearTypeGridFit (best quality).&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Enjoy :)&lt;/p&gt;</description></item><item><dc:creator>Anatoly Lubarsky</dc:creator><title>.NET: How to Make HTTP Request and Get Response</title><link>http://blogs.x2line.com/al/archive/2008/08/29/3544.aspx</link><pubDate>Fri, 29 Aug 2008 00:34:00 GMT</pubDate><guid>http://blogs.x2line.com/al/archive/2008/08/29/3544.aspx</guid><wfw:comment>http://blogs.x2line.com/al/comments/3544.aspx</wfw:comment><comments>http://blogs.x2line.com/al/archive/2008/08/29/3544.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.x2line.com/al/comments/commentRss/3544.aspx</wfw:commentRss><trackback:ping>http://blogs.x2line.com/al/services/trackbacks/3544.aspx</trackback:ping><description>&lt;p&gt;There are so many ways to query external url in .NET, people can use so many approaches and .NET Framework classes available - it's crazy. Quering external urls via HTTP today is a common task many developers facing.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;There are many REST (or other types of) open APIs created by external services.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Below I decided to post an example of how to do it the right way (as far as I can see it). This schematic function supports both POST and GET requests, highly scalable and the most important - it is designed as low level infrastructure function (i.e. uses simple types and bubbles exceptions).&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
public string GetHttpResponse(string requestUrl, byte[] data)
{
    // declare objects
    string responseData = String.Empty;
    HttpWebRequest req = null;
    HttpWebResponse resp = null;
    StreamReader strmReader = null;

    try
    {
        req = (HttpWebRequest)HttpWebRequest.Create(requestUrl);
        

        // set HttpWebRequest properties here (Method, ContentType, etc)
        // some code

        // in case of POST you need to post data
        if ((data != null) &amp;&amp; (data.Length &gt; 0))
        {
            using (Stream strm = req.GetRequestStream())
            {
                strm.Write(data, 0, data.Length);
            }
        }

        resp = (HttpWebResponse)req.GetResponse();
        strmReader = new StreamReader(resp.GetResponseStream());
        responseData = strmReader.ReadToEnd().Trim();
    }
    catch (Exception ex)
    {
        throw;
    }
    finally
    {
        if (req != null)
        {
            req = null;
        }

        if (resp != null)
        {
            resp.Close();
            resp = null;
        }
    }

    return responseData;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;P.S. - HttpWebRequest proved to be the most reliable for me.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Enjoy&lt;/p&gt;</description></item><item><dc:creator>Anatoly Lubarsky</dc:creator><title>How to: Get Total Physical Memory</title><link>http://blogs.x2line.com/al/archive/2008/06/14/3459.aspx</link><pubDate>Sat, 14 Jun 2008 05:59:00 GMT</pubDate><guid>http://blogs.x2line.com/al/archive/2008/06/14/3459.aspx</guid><wfw:comment>http://blogs.x2line.com/al/comments/3459.aspx</wfw:comment><comments>http://blogs.x2line.com/al/archive/2008/06/14/3459.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.x2line.com/al/comments/commentRss/3459.aspx</wfw:commentRss><trackback:ping>http://blogs.x2line.com/al/services/trackbacks/3459.aspx</trackback:ping><description>&lt;p&gt;Q: My app needs to know how much RAM the machine it's running on has. How can this information be aquired ?&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Is there any _managed_ way of getting total physical memory installed in the machine ?&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;You can retrieve the amount of physical memory on the computer by using WMI (You could use a WMI query, the property is "TotalPhysicalMemory" which is in the "Win32_ComputerSystem" class.). However: WMI would  almost always be the slowest way to retrieve system values using C#.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Therefore I advice to use Win32 API - &lt;b&gt;GlobalMemoryStatus&lt;/b&gt; function included in &lt;i&gt;kernel32.dll&lt;/i&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
public struct MemoryStatus 
{ 
    public uint Length;  
    public uint MemoryLoad; 
    public uint TotalPhysical; 
    public uint AvailablePhysical; 
    public uint TotalPageFile; 
    public uint AvailablePageFile; 
    public uint TotalVirtual; 
    public uint AvailableVirtual; 
} 

[DllImport("kernel32.dll")] 
public static extern void GlobalMemoryStatus(out MemoryStatus stat);
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;From managed code we can use it  like so:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
MemoryStatus stat = new MemoryStatus();
GlobalMemoryStatus(out stat);
long ram = (long)stat.TotalPhysical;
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Hope this helps.&lt;/p&gt;</description></item><item><dc:creator>Anatoly Lubarsky</dc:creator><title>Reducing Memory Footprint of any Process with EmptyWorkingSet</title><link>http://blogs.x2line.com/al/archive/2008/04/20/3394.aspx</link><pubDate>Sun, 20 Apr 2008 21:07:00 GMT</pubDate><guid>http://blogs.x2line.com/al/archive/2008/04/20/3394.aspx</guid><wfw:comment>http://blogs.x2line.com/al/comments/3394.aspx</wfw:comment><comments>http://blogs.x2line.com/al/archive/2008/04/20/3394.aspx#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://blogs.x2line.com/al/comments/commentRss/3394.aspx</wfw:commentRss><trackback:ping>http://blogs.x2line.com/al/services/trackbacks/3394.aspx</trackback:ping><description>&lt;p&gt;Ever wondered why does .NET winform application takes so much memory on startup ? It is obvious that most of this memory is not in use. The reason is that JIT compiler and the whole winforms engine is loaded into the process. However it is possible to remove as many pages as possible from the working set of the specified process using &lt;i&gt;EmptyWorkingSet&lt;/i&gt; from &lt;b&gt;psapi.dll&lt;/b&gt;.&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
[DllImport("psapi.dll")]
static extern int EmptyWorkingSet(IntPtr hwProc);
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;From managed code we can use it  like so (for the current process):&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
static void ClearMemory()
{
    EmptyWorkingSet(Process.GetCurrentProcess().Handle);
}
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;However it is possible to use this function for any process which handle must have the PROCESS_QUERY_INFORMATION and PROCESS_SET_INFORMATION access rights. Be careful using EmptyWorkingSet since the process will allocate the memory again in the future when needed.&lt;/p&gt;</description></item><item><dc:creator>Anatoly Lubarsky</dc:creator><title>C# Win32 API: Flash Window (FlashWindowEx)</title><link>http://blogs.x2line.com/al/archive/2008/04/19/3392.aspx</link><pubDate>Sat, 19 Apr 2008 21:11:00 GMT</pubDate><guid>http://blogs.x2line.com/al/archive/2008/04/19/3392.aspx</guid><wfw:comment>http://blogs.x2line.com/al/comments/3392.aspx</wfw:comment><comments>http://blogs.x2line.com/al/archive/2008/04/19/3392.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.x2line.com/al/comments/commentRss/3392.aspx</wfw:commentRss><trackback:ping>http://blogs.x2line.com/al/services/trackbacks/3392.aspx</trackback:ping><description>&lt;p&gt;Ever tried to flash a window using managed code ? The following method will flash the window title bar or the window taskbar button. Since there is no managed API available for this functionality - need to wrap a method imported from user32: &lt;i&gt;FlashWindowEx&lt;/i&gt;:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
[DllImport("user32.dll")]
static extern Int32 FlashWindowEx(ref FLASHWINFO pwfi);
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Where FLASHWINFO struct is defined like so:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
[StructLayout(LayoutKind.Sequential)]
public struct FLASHWINFO
{
    public UInt32 cbSize;
    public IntPtr hwnd;
    public Int32 dwFlags;
    public UInt32 uCount;
    public Int32 dwTimeout;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Where &lt;i&gt;dwFlags&lt;/i&gt; can be one of the following:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
// stop flashing
FLASHW_STOP = 0; 

// flash the window title 
FLASHW_CAPTION = 1; 

// flash the taskbar button
FLASHW_TRAY = 2; 

// 1 | 2
FLASHW_ALL = 3; 

// flash continuously 
FLASHW_TIMER = 4; 

// flash until the window comes to the foreground 
FLASHW_TIMERNOFG = 12; 
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;So the typical C# call will look like so:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
public static bool Flash()
{
    FLASHWINFO fw = new FLASHWINFO();

    fw.cbSize = Convert.ToUInt32(Marshal.SizeOf(typeof(FLASHWINFO)));
    fw.hwnd = this.Handle;
    fw.dwFlags = 2;
    fw.uCount = UInt32.MaxValue;

    FlashWindowEx(ref fw);
}
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;See some other &lt;a href="http://blogs.x2line.com/al/category/95.aspx"&gt;C# Win32 API tips and tricks&lt;/a&gt;. Enjoy :)&lt;/p&gt;</description></item><item><dc:creator>Anatoly Lubarsky</dc:creator><title>Calculate Euler Number with Recursion</title><link>http://blogs.x2line.com/al/archive/2008/03/11/3377.aspx</link><pubDate>Tue, 11 Mar 2008 04:01:00 GMT</pubDate><guid>http://blogs.x2line.com/al/archive/2008/03/11/3377.aspx</guid><wfw:comment>http://blogs.x2line.com/al/comments/3377.aspx</wfw:comment><comments>http://blogs.x2line.com/al/archive/2008/03/11/3377.aspx#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blogs.x2line.com/al/comments/commentRss/3377.aspx</wfw:commentRss><trackback:ping>http://blogs.x2line.com/al/services/trackbacks/3377.aspx</trackback:ping><description>&lt;p&gt;I recently went through several posts I had made on one of the development forums back then in 2005. I've found one of them interesting and wanted to repost it here. The question went like this:&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;i&gt;"How can I calculate euler number with recursion ?"&lt;/i&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/E_%28mathematical_constant%29" target="_blank"&gt;Euler number&lt;/a&gt; (or &lt;b&gt;e&lt;/b&gt;) can be calculated with the following formula in math:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;sum = 1/0! + 1/1! + 1/2! + ... + 1/n!&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Here one can notice the use of the Factorial function which can be implemented via recursion itself  like so:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
int Factorial(int n) 
{
    if (n == 0) 
    {
        return 1;
    }

    return n * Factorial(n - 1);
}
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;After we know how to implement Factorial we can implement &lt;b&gt;Euler number&lt;/b&gt; using recursion as well:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
double EulerNumber(int n) 
{
    if (n == 0) 
    {
        return 1;
    }

    return 1.0/Factorial(n) + EulerNumber(n - 1);
}
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Enjoy :)&lt;/p&gt;</description></item><item><dc:creator>Anatoly Lubarsky</dc:creator><title>HOW TO: Remove Last Character from String </title><link>http://blogs.x2line.com/al/archive/2008/03/10/3369.aspx</link><pubDate>Mon, 10 Mar 2008 03:36:00 GMT</pubDate><guid>http://blogs.x2line.com/al/archive/2008/03/10/3369.aspx</guid><wfw:comment>http://blogs.x2line.com/al/comments/3369.aspx</wfw:comment><comments>http://blogs.x2line.com/al/archive/2008/03/10/3369.aspx#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blogs.x2line.com/al/comments/commentRss/3369.aspx</wfw:commentRss><trackback:ping>http://blogs.x2line.com/al/services/trackbacks/3369.aspx</trackback:ping><description>&lt;p&gt;Very often during development we need to remove the last character from a string.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;It could be a trailing slash or a trailing comma as a result (side effect ?) of building delimited strings.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;There are many ways to do that in C#, however I like the following one for its simplicity and good performance:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;
str.Remove(str.Length - 1, 1);
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Enjoy&lt;/p&gt;</description></item><item><dc:creator>Anatoly Lubarsky</dc:creator><title>HOW TO: Read From a Locked Text File</title><link>http://blogs.x2line.com/al/archive/2008/01/26/3342.aspx</link><pubDate>Sat, 26 Jan 2008 23:12:00 GMT</pubDate><guid>http://blogs.x2line.com/al/archive/2008/01/26/3342.aspx</guid><wfw:comment>http://blogs.x2line.com/al/comments/3342.aspx</wfw:comment><comments>http://blogs.x2line.com/al/archive/2008/01/26/3342.aspx#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://blogs.x2line.com/al/comments/commentRss/3342.aspx</wfw:commentRss><trackback:ping>http://blogs.x2line.com/al/services/trackbacks/3342.aspx</trackback:ping><description>&lt;p&gt;Q: I'm trying to read a txt file using StreamReader, but the file is locked by another process. The problem is that, since this is a log file I can't stop the other process that is using it.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;Even if one makes sure to specify the proper FileAccess and FileShare modes when opening the file she won't be able to read it if the other program has opened the file with an exclusive lock.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Since this is a very common problem I wanted to share a small but useful tip of how to do that:&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Before you open the file simply copy it to ---&amp;gt; C:\Documents and Settings\&amp;lt;username&amp;gt;\Local Settings\Temp\. REASON: Avoids file access violations under Windows. Now open and read the copied file.&lt;/p&gt;</description></item><item><dc:creator>Anatoly Lubarsky</dc:creator><title>Solution for MSI Error 2869 on Windows Vista</title><link>http://blogs.x2line.com/al/archive/2007/07/20/3210.aspx</link><pubDate>Fri, 20 Jul 2007 17:23:00 GMT</pubDate><guid>http://blogs.x2line.com/al/archive/2007/07/20/3210.aspx</guid><wfw:comment>http://blogs.x2line.com/al/comments/3210.aspx</wfw:comment><comments>http://blogs.x2line.com/al/archive/2007/07/20/3210.aspx#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://blogs.x2line.com/al/comments/commentRss/3210.aspx</wfw:commentRss><trackback:ping>http://blogs.x2line.com/al/services/trackbacks/3210.aspx</trackback:ping><description>&lt;h4&gt;What is MSI error 2869&lt;/h4&gt;
&lt;p&gt;It turns out that &lt;i&gt;Error 2869&lt;/i&gt; is the common issue with MSI installations on Windows Vista.&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;&lt;i&gt;"The installer has encountered an unexpected error installing this package. This may indicate a problem with this package. The error code is 2869"&lt;/i&gt;&lt;/p&gt;&lt;br /&gt;
&lt;p&gt;Even MSI installations provided by Microsoft have to deal with this error which is trying to tell that the user does not have administrative privileges to install. However she does have administrative privileges (lol).&lt;/p&gt;&lt;br /&gt;
&lt;h4&gt;What is User Access Control&lt;/h4&gt;
&lt;p&gt;This happens because of UAC (&lt;i&gt;user access control&lt;/i&gt;) feature of Windows Vista. What is user access control ? To make the long story short - if you are defined as administrator on Vista - you are not.. (lol). You are only temporary granted administrator privileges when running programs.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;Therefore &lt;b&gt;MSI Custom Actions&lt;/b&gt; that interact with the system and require administrative privileges will fail to run because &lt;b&gt;MSI Custom Actions&lt;/b&gt; will impersonate by default.&lt;/p&gt;&lt;br&gt;
&lt;p&gt;BTW, quick workaround will be running:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;msiexec /i MySetup.msi&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;from a command line prompt as administrator.&lt;/p&gt;&lt;br /&gt;
&lt;h4&gt;Solution&lt;/h4&gt;
&lt;p&gt;It is possible to mark Custom Actions as &lt;b&gt;msidbCustomActionTypeNoImpersonate&lt;/b&gt; in MSI. So one can edit MSI with ORCA and patch Custom Actions table updating Type column to be &lt;b&gt;msidbCustomActionTypeNoImpersonate&lt;/b&gt; according to the &lt;a href="http://msdn2.microsoft.com/en-us/library/Aa368069.aspx" target="_blank"&gt;Custom Action In-Script Execution Options&lt;/a&gt; table. Usually it will be enough to add 1024 to the Type column in the Custom Actions for Custom Actions of install, uninstall, rollback and commit (anyway - those that require administrative privileges).&lt;/p&gt;&lt;br /&gt;
&lt;h4&gt;Visual Studio 2005&lt;/h4&gt;
&lt;p&gt;Bonus for Visual Studio 2005 developers. I advice to use &lt;b&gt;WiRunSQL.vbs&lt;/b&gt; to patch MSI automatically (Google for it :)). Go to the properties of your setup project and define post-build event that utilizes WiRunSQL.vbs. Like so:&lt;/p&gt;&lt;br /&gt;
&lt;pre&gt;@echo off
cscript /nologo "WiRunSQL.vbs" "MySetup.msi" 
"UPDATE CustomAction SET Type = 3585 WHERE Type = 1537"
&lt;/pre&gt;&lt;br /&gt;
&lt;p&gt;Enjoy&lt;/p&gt;</description></item></channel></rss>