<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>&#60;jco-blog&#047;&#62; &#187; C#</title>
	<atom:link href="http://www.elementalp.com/blog/index.php/category/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.elementalp.com/blog</link>
	<description>Software Development Project Notes</description>
	<lastBuildDate>Tue, 05 Jan 2016 18:59:50 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
	<item>
		<title>Find definitions and references of SQL Command Variables in a SQL script</title>
		<link>http://www.elementalp.com/blog/index.php/2015/07/23/find-definitions-and-references-of-sql-command-variables-in-a-sql-script/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/07/23/find-definitions-and-references-of-sql-command-variables-in-a-sql-script/#comments</comments>
		<pubDate>Thu, 23 Jul 2015 18:34:29 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[My Specific Situation]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=285</guid>
		<description><![CDATA[(This is a C# LinqPad script) Using setvar in T-SQL Finds the SQL Command Variable definitions in a SQL script and parses their names and values. Finds the SQL Command Variable references and parses their names. Determines which references have no definitions. Determines which definitions have no references. The definition names and reference names are [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>(This is a C# LinqPad script)</p>
<p><a href="http://www.elementalp.com/blog/index.php/2015/06/24/sql-cmd/"><span style="color: #0066cc;">Using setvar in T-SQL </span></a></p>
<p>Finds the SQL Command Variable definitions in a SQL script and parses their names and values.<br />
Finds the SQL Command Variable references and parses their names.<br />
Determines which references have no definitions.<br />
Determines which definitions have no references.</p>
<p>The definition names and reference names are case insensitive.<br />
A definition is in the form of :setvar name &#8220;value&#8221;<br />
A reference is in the form of $(name)</p><pre class="crayon-plain-tag">void Main()
{
	//sql file path
	string file = @"C:\temp\my.sql";
	
	//Token definition pattern for :setvar name "value"
	string tokenDefPattern = @"(\:setvar [^""]* ""[^""]*"")";
	string tokenDefNamePattern = @"\:setvar ([^ ""]*)";
	string tokenDefValuePattern = @"""([^""]*)""";	
	
	//Token reference pattern for $(name)
	string tokenRefPattern = @"(\$\([^)]*\))";
	string tokenRefNamePattern = @"\$\(([^)]*)\)";
	
	string text = System.IO.File.ReadAllText(file);
	
	var tokenDefs = Token.GetAllFirstCapturedMatches(text,tokenDefPattern).Distinct().ToDictionary(x=&gt;x,y=&gt;new Token(y,tokenDefNamePattern,tokenDefValuePattern));
	var tokenRefs = Token.GetAllFirstCapturedMatches(text,tokenRefPattern).Distinct().ToDictionary(x=&gt;x,y=&gt;new Token(y,tokenRefNamePattern,null));
	
	tokenDefs.Select(x=&gt;x.Value).OrderBy (x =&gt; x.Name).ToList().Dump("Token Definitions");
	tokenDefs.Where(x=&gt; !tokenRefs.Any(y =&gt; y.Value.Name == x.Value.Name)).Select(x=&gt;x.Value).OrderBy(x =&gt; x.Name).ToList().Dump("Token definitions without a reference");
	tokenRefs.Where(x=&gt; !tokenDefs.Any(y =&gt; y.Value.Name == x.Value.Name)).Select(x=&gt;x.Value).OrderBy(x =&gt; x.Name).ToList().Dump("Token references without a definition");
}

public class Token
{
	public Token(){}
	
	public Token(string Raw, string namePattern, string  valuePattern)
	{
		this.Raw = Raw;
		if(!string.IsNullOrWhiteSpace(namePattern)) Name = Token.GetFirstCapturedMatch(Raw,namePattern);
		if(!string.IsNullOrWhiteSpace(valuePattern)) Value = Token.GetFirstCapturedMatch(Raw,valuePattern);
	}

	public string Name {get;set;}
	public string Value {get;set;}
	public string Raw {get;set;}
	
	public static string GetFirstCapturedMatch(string value, string pattern)
	{
		var match = Regex.Match(value,pattern);
		if(match!=null &amp;&amp; match.Success &amp;&amp; match.Groups.Count&gt;1)
		{
			return match.Groups[1].Value;
		}
		return null;
	}
	
	public static List&lt;string&gt; GetAllFirstCapturedMatches(string value, string pattern)
	{
		var list = new List&lt;string&gt;();
		var matches = Regex.Matches(value,pattern);
		foreach(Match match in matches)
		{
			if(match!=null &amp;&amp; match.Success &amp;&amp; match.Groups.Count&gt;1) 
			{
				list.Add(match.Groups[1].Value);
			}
		}
		return list;
	}
}</pre><p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/07/23/find-definitions-and-references-of-sql-command-variables-in-a-sql-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ping until a machine responds</title>
		<link>http://www.elementalp.com/blog/index.php/2015/06/30/ping-until-a-machine-responds/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/06/30/ping-until-a-machine-responds/#comments</comments>
		<pubDate>Tue, 30 Jun 2015 17:25:46 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=265</guid>
		<description><![CDATA[It appears that the virtual machine manager in HyperV (VMM) reports the VM as running though the OS may not yet be fully loaded. We need to wait until the OS is responsive before continuing VM configuration. This observed behavior is more empirical than scientific and requires investigation, but a stop-gap solution is to wait until the VMM reports that the VM is running and then [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>It appears that the virtual machine manager in HyperV (VMM) reports the VM as running though the OS may not yet be fully loaded. We need to wait until the OS is responsive before continuing VM configuration. This observed behavior is more empirical than scientific and requires investigation, but a stop-gap solution is to wait until the VMM reports that the VM is running and then wait for the machine to respond to pings. This code does the second part.</p><pre class="crayon-plain-tag">using System.Net.NetworkInformation;

public class Test
{
	public static bool Ping(string name, int waitForPostivePingTimeout = 0) 
	{
		if(string.IsNullOrEmpty(name)) return false;
		if(waitForPostivePingTimeout &lt; 0) waitForPostivePingTimeout = 0;
		var timeout = DateTime.Now.AddMilliseconds(waitForPostivePingTimeout);
		
		do
		{
			try
			{
				Ping p = new Ping();
				PingReply reply = p.Send(name, 2000);
				if(reply.Status == IPStatus.Success) return true;
			}
			catch{}
		} while(DateTime.Now &lt; timeout);
		return false;
	}
}</pre><p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/06/30/ping-until-a-machine-responds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C# Current Class.Method Logging</title>
		<link>http://www.elementalp.com/blog/index.php/2015/05/26/c-current-class-method-logging/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/05/26/c-current-class-method-logging/#comments</comments>
		<pubDate>Tue, 26 May 2015 23:09:26 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=173</guid>
		<description><![CDATA[[crayon-6a06f750ee29b081740203/] Note that this doesn&#8217;t work so well with method name obfuscation! [crayon-6a06f750ee343461124789/] Results [Operations] Foo.DoSomething : something 1 Foo.DoSomethingElse : something else 1 Foo.DoSomething : something 2]]></description>
				<content:encoded><![CDATA[<p></p><pre class="crayon-plain-tag">originally posted 2015-3-2</pre><p></p>
<p>Note that this doesn&#8217;t work so well with method name obfuscation!</p>
<p></p><pre class="crayon-plain-tag">using System.Reflection;
void Main()
{
  new Foo().DoSomething();
  Helper.GetOperationsAsString().Dump(&quot;Operations&quot;);
}

public class Foo
{
    public void DoSomething()
    {
        var mb = MethodBase.GetCurrentMethod();
        Helper.AppendOperation(mb, &quot;something 1&quot;);
        DoSomethingElse();
        Helper.AppendOperation(mb, &quot;something 2&quot;);
    }

    public void DoSomethingElse()
    {
        var mb = MethodBase.GetCurrentMethod();
        Helper.AppendOperation(mb, &quot;something else 1&quot;);
    }
}

public static class Helper
{  
    public static List&lt;string&gt; Operations = new List&lt;string&gt;();

    public static string GetOperationsAsString()
    {
         return String.Join(&quot;\n&quot;, Operations.ToArray());
    }

    public static void AppendOperation(System.Reflection.MethodBase mb, string message = null, params object[] messageArgs)
    {
        if (mb != null)
        {
            string msg = string.Empty;
            if (!string.IsNullOrEmpty(message))
            {
                msg = &quot; : &quot; + string.Format(message, messageArgs);
            }
            Operations.Add(string.Format(&quot;{0}.{1}{2}&quot;, mb.DeclaringType.Name, mb.Name, msg));
        }
    }
}</pre><p><strong>Results</strong><br />
[Operations]<br />
Foo.DoSomething : something 1<br />
Foo.DoSomethingElse : something else 1<br />
Foo.DoSomething : something 2</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/05/26/c-current-class-method-logging/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WCF Client-Side Exceptions (getting full service-side exception detail)</title>
		<link>http://www.elementalp.com/blog/index.php/2015/05/26/wcf-client-side-exceptions-getting-full-service-side-exception-detail/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/05/26/wcf-client-side-exceptions-getting-full-service-side-exception-detail/#comments</comments>
		<pubDate>Tue, 26 May 2015 23:04:22 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=171</guid>
		<description><![CDATA[[crayon-6a06f750eecd6908511827/] WCF throws System.ServiceModel.FaultExceptions (FE) between the client and server. The FE is a System.Exception so the client does not need to explicitly catch FaultException, but the FE is missing something. It does not take an InnerException in its constructor, so the server-side chain of exceptions and stack trace data are not available to the [&#8230;]]]></description>
				<content:encoded><![CDATA[<p></p><pre class="crayon-plain-tag">originally posted 2012-8-24</pre><p>WCF throws System.ServiceModel.FaultExceptions (FE) between the client and server. The FE is a System.Exception so the client does not need to explicitly catch FaultException, but the FE is missing something. It does not take an InnerException in its constructor, so the server-side chain of exceptions and stack trace data are not available to the client. The typical response to this is &#8220;That&#8217;s the way it&#8217;s supposed to work!&#8221;, but if you own/control the consumers of your web service and you want the exception chain and stack trace data, then you&#8217;ll want to use FaultException.</p>
<p>The first thing is to decorate your service operations with the FaultContract attribute:</p><pre class="crayon-plain-tag">//service interface
public interface IService
{

 [OperationContract(IsOneWay = false)]
 [FaultContract(typeof(ExceptionDetail))]
 Foo GetFoo(Guid id);
}</pre><p>By default, the service implementation will throw all unhandled exceptions back to the client as a regular FaultException. To avoid this, catch exceptions and re-throw them as FaultException as such&#8230;</p><pre class="crayon-plain-tag">//service implementation
public sealed partial class Service : IService
{
 Foo IService.GetFoo(Guid id)
        {
            try
            {
         
                return FooLib.GetFoo(id);
            }
            catch (Exception ex)
            {
                throw new FaultException&lt;ExceptionDetail&gt;(new ExceptionDetail(ex), ex.Message);
            }
        }
}</pre><p>Great! All that detail is on its way to your client.</p>
<p>FaultException and FaultException<>; are derived from System.Exception, so when you don&#8217;t care about the detail, just catch Exception. When you want the detail, catch FaultException and inspect &#8230;</p><pre class="crayon-plain-tag">try
{
 ...
 ServiceReference.Foo foo = proxy.CreateFoo(fooId);

}
catch (FaultException&lt;ExceptionDetail&gt; fe)
{
 string message = fe.Message; //the equivalent of Exception.Message

 ExceptionDetail detail = fe.Detail; //the latest exception data
 string trace = detail.StackTrace; //stack info
 ExceptionDetail nextError = detail.InnerException; //exception chain

}
catch (Exception ex)
{
 ...
}</pre><p>An instance of ExceptionDetail stores a copy of the underlying Exception data as well as the Exception’s InnerException data, which is also converted to a ExceptionDetail, thus preserving the data of the Exception chain. This means that custom exception types thrown by the server cannot specifically be caught by the client. It also means that the client does not need to reference these exception types. However, the client can determine the type of exception thrown by the server&#8230;</p>
<p>The client wishes to detect the ABC.EmptyGuidException thrown by a library called by the service implementation.</p><pre class="crayon-plain-tag">//a library called by the service implementation
public static class FooLib
{
 public static GetFoo(Guid id)
 {
  if(Guid.Equals(Guid.Empty) throw new ABC.EmptyGuidException(&quot;No!&quot;)
  ...
 
 }
}
 
//the client 
try
{
 ...
 ServiceReference.Foo foo = proxy.CreateFoo(fooId);

}
catch (FaultException&lt;ExceptionDetail&gt; fe)
 {
 ExceptionDetail detail = fe.Detail;
 switch(detail.Type) //this is the type's FullName!
 {
  case &quot;ABC.EmptyGuidException&quot;:
   //do something here
   break;
  ...
 }
}
catch (Exception ex)
{
 ...
}</pre><p>Clunky, but attainable.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/05/26/wcf-client-side-exceptions-getting-full-service-side-exception-detail/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unix Timestamp in SQL Server</title>
		<link>http://www.elementalp.com/blog/index.php/2015/05/26/unix-timestamp-in-sql-server/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/05/26/unix-timestamp-in-sql-server/#comments</comments>
		<pubDate>Tue, 26 May 2015 21:41:26 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=139</guid>
		<description><![CDATA[[crayon-6a06f750ef984974961960/] A Unix timestamp is defined as the number of seconds elapsed between January 1, 1970 00:00:00 and a given date/time expressed in Universal Coordinated Time. A timestamp can be generated up to the date 2038-1-19 3:14:7 before overflowing a 32-bit integer. http://en.wikipedia.org/wiki/Unix_time [crayon-6a06f750efa21066098823/] An alternative, encoding a DateTime into a BigInt and back again. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p></p><pre class="crayon-plain-tag">originally posted 2013-7-25</pre><p></p>
<div><span style="font-family: helvetica; font-size: small;">A Unix timestamp is defined as the number of seconds elapsed between January 1, 1970 00:00:00 and a given date/time expressed in Universal Coordinated Time.<br />
A timestamp can be generated up to the date 2038-1-19 3:14:7 before overflowing a 32-bit integer.<br />
<a href="http://en.wikipedia.org/wiki/Unix_time">http://en.wikipedia.org/wiki/Unix_time</a> </span></div>
<p></p>
<p></p><pre class="crayon-plain-tag">--create a Unix timestamp from current server UTC time
create function [dbo].[fGetUnixTimestamp]()
returns int
as 
begin
   return datediff(s,'1970-1-1',sysutcdatetime());
end
go

--convert a Unix timestamp to a datetime in UTC
create function [dbo].[fConvertUnixTimestampToDateTime] (@timestamp int)
returns datetime
as
begin
   return dateadd(s,@timestamp,'1970-1-1')
end
go

--convert a Unix timestamp to a datetime adjusted to the server's time zone
create function [dbo].[fConvertUnixTimestampToLocalDateTime] (@timestamp int)
returns datetime
as
begin
   return dateadd(hh,datediff(hh,sysutcdatetime(),getdate()),dateadd(s,@timestamp,'1970-1-1'))
end
go

--[TEST]

declare @ts int
select @ts = [dbo].[fGetUnixTimestamp]()

select [Timestamp] = @ts
,[UTC Time] = [dbo].[fConvertUnixTimestampToDateTime](@ts)
,[Local Time] = [dbo].[fConvertUnixTimestampToLocalDateTime](@ts)
,[Local Time Zone Offset from UTC] = datediff(hh,sysutcdatetime(),getdate())

/*
[EXAMPLE RESULTS]
Timestamp Local Time = 1374776005   
UTC Time  = Jul 25 2013  6:13PM
Local Time = Jul 25 2013 11:13AM
Local Time Zone Offset from UTC = -7
*/</pre><p>An alternative, encoding a DateTime into a BigInt and back again.</p><pre class="crayon-plain-tag">create function [dbo].[fEncodeDateTimeToBigInt](@dt datetime)
returns bigint
as
begin
 --note: resolution is to the second
 if(@dt is not null)
  return convert(bigint,
   DATEPART(second, @dt) +
   DATEPART(minute, @dt) * 100 +
   DATEPART(hour, @dt) * 10000 +
   DATEPART(day, @dt) * 1000000 +
   DATEPART(month, @dt) * 100000000 +
   DATEPART(year, @dt) * 10000000000)
 return null;
end
go

create function [dbo].[fDecodeBigIntToDateTime](@bi bigint)
returns datetime
as
begin
 if(@bi is not null)
 begin
  declare @str nvarchar(30)
  set @str = convert(nvarchar(30),@bi)
     if(len(@str)=14) return convert(datetime,
  substring(@str,1,4) + '-' 
  + substring(@str,5,2) + '-' 
  + substring(@str,7,2) + ' ' 
  + substring(@str,9,2) + ':' 
  + substring(@str,11,2) + ':' 
  + substring(@str,13,2));
 end
 return null;
end

--TEST
declare @nowUtc datetime
set @nowUtc = sysutcdatetime();

declare @bi bigint
set @bi = [dbo].[fEncodeDateTimeToBigInt](@nowUtc);

declare @dt datetime 
set @dt = [dbo].[fDecodeBigIntToDateTime](@bi);

select [Input DateTime] = @nowUtc, [Encoded BigInt] = @bi, [Decoded DateTime] = @dt

/*
[Example Results]
Input DateTime = 2013-07-25 20:55:30.293
Encoded BigInt = 20130725205530 
Decoded DateTime = 2013-07-25 20:55:30.000
*/</pre><p>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/05/26/unix-timestamp-in-sql-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows Forms Inactivity Timeout Class</title>
		<link>http://www.elementalp.com/blog/index.php/2015/05/26/windows-forms-inactivity-timeout-class/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/05/26/windows-forms-inactivity-timeout-class/#comments</comments>
		<pubDate>Tue, 26 May 2015 21:30:16 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=135</guid>
		<description><![CDATA[[crayon-6a06f750f0a2a136599037/] [crayon-6a06f750f0aba376875662/]]]></description>
				<content:encoded><![CDATA[<p></p><pre class="crayon-plain-tag">originally posted 2013-8-29</pre><p><a href="http://www.elementalp.com/blog/wp-content/uploads/2015/05/WinFormInactivity.png"><img class="alignnone size-full wp-image-136" src="http://www.elementalp.com/blog/wp-content/uploads/2015/05/WinFormInactivity.png" alt="WinFormInactivity" width="598" height="526" /></a></p><pre class="crayon-plain-tag">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace NPT.Common
{
    /// &amp;amp;lt;summary&amp;amp;gt;
    /// Polls the system periodically and raises the IsIdle event if the
    /// user interface has been idle for at least the specfied number of seconds.
    /// Stops polling once the IsIdle is fired, use Start() to resume polling.
    /// &amp;amp;lt;/summary&amp;amp;gt;
    public class IdleTimer : IDisposable
    {
        [DllImport(&quot;user32.dll&quot;)]
        static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        internal struct LASTINPUTINFO
        {
            public Int32 cbSize;
            public Int32 dwTime;
        }

        private int timeoutSeconds = 0;
        private int pollSeconds = 0;
        private System.Timers.Timer timer = null;
        private System.ComponentModel.ISynchronizeInvoke sychronizingObject = null;

        //ctor
        public IdleTimer(int idleTimeoutSeconds, System.ComponentModel.ISynchronizeInvoke sychronizingObject = null)
        {
            if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debug.WriteLine(&quot;IdleTimer: Created&quot;);
            pollSeconds = 5;
            if (idleTimeoutSeconds &amp;amp;lt; 5) 
            {
                idleTimeoutSeconds = 5;
                pollSeconds = 4;
            }
            this.timeoutSeconds = idleTimeoutSeconds;
            this.sychronizingObject = sychronizingObject;

        public void Start()
        {
            System.Diagnostics.Debug.WriteLine(&quot;IdleTimer: Started&quot;);
            StartPolling();
        }

        public void Stop()
        {
            System.Diagnostics.Debug.WriteLine(&quot;IdleTimer: Stopped&quot;);
            StopPolling();
        }

        //event
        public delegate void IsIdleEventHandler(object sender, IdleTimerEventArgs e);
        public event IsIdleEventHandler IsIdle;
        protected virtual void OnIsIdle(IdleTimerEventArgs e)
        {
            //raise event
            StopPolling();
            if (IsIdle != null) IsIdle(this, e);
        }

        //start polling idle time
        private void StartPolling()
        {
            if (timer == null)
            {
                timer = new System.Timers.Timer(pollSeconds * 1000);
                timer.Elapsed += new System.Timers.ElapsedEventHandler(Poll);
                if (sychronizingObject != null) timer.SynchronizingObject = sychronizingObject;
            }
            timer.Start();
        }

        //stop polling idle time
        private void StopPolling()
        {
            if (timer != null) timer.Stop();
        }

        //poll idle time
        private void Poll(object sender, System.Timers.ElapsedEventArgs e)
        {
            StopPolling();
            int idleSeconds = GetIdleTime();
            if (idleSeconds &amp;amp;gt;= timeoutSeconds)
            {
                if (System.Diagnostics.Debugger.IsAttached)
                {
                    System.Diagnostics.Debug.WriteLine(&quot;IdleTimer: Idle - Timeout = {1} seconds, Idle time = {0} seconds&quot;, idleSeconds, timeoutSeconds);
                }

                //system has been idle for at least timeoutSeconds seconds
                OnIsIdle(new IdleTimerEventArgs(idleSeconds:idleSeconds,timeoutSeconds:timeoutSeconds)); 
            }
            StartPolling();
        }

        /// &amp;amp;lt;summary&amp;amp;gt;
        /// Returns system idle time in seconds
        /// &amp;amp;lt;/summary&amp;amp;gt;
        /// &amp;amp;lt;returns&amp;amp;gt;&amp;amp;lt;/returns&amp;amp;gt;
        public int GetIdleTime()
        {
            int systemUptime = Environment.TickCount;
            int lastInputTicks = 0;
            int idleTicks = 0;

            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = (Int32)Marshal.SizeOf(lastInputInfo);
            lastInputInfo.dwTime = 0;

            if (GetLastInputInfo(ref lastInputInfo))
            {
                lastInputTicks = (int)lastInputInfo.dwTime;
                idleTicks = systemUptime - lastInputTicks;
            }
            Int32 seconds = idleTicks / 1000;
            return seconds;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                StopPolling();
                timer = null;
                sychronizingObject = null;
                if (System.Diagnostics.Debugger.IsAttached)
                {
                    System.Diagnostics.Debug.WriteLine(&quot;IdleTimer: Disposed&quot;);
                }
            }
        }
    }

    public class IdleTimerEventArgs : EventArgs
    {
        public IdleTimerEventArgs(int idleSeconds, int timeoutSeconds)
        {
            IdleSeconds = idleSeconds;
            TimeoutSeconds = timeoutSeconds;
        }

        public int IdleSeconds { get; set; }
        public int TimeoutSeconds {get; set;}
    }
}

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Threading;

//obsolete: [assembly: SecurityPermission(SecurityAction.RequestMinimum, UnmanagedCode = true)]
namespace System.Windows.Forms
{
    public class MessageBoxEx
    {
        public static DialogResult Show(string text, uint timeoutSeconds)
        {
            Setup(&quot;&quot;, timeoutSeconds);
            return MessageBox.Show(text);
        }

        public static DialogResult Show(string text, string caption, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(text, caption);
        }

        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(text, caption, buttons);
        }

        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(text, caption, buttons, icon);
        }

        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(text, caption, buttons, icon, defButton);
        }

        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(text, caption, buttons, icon, defButton, options);
        }

        public static DialogResult Show(IWin32Window owner, string text, uint timeoutSeconds)
        {
            Setup(&quot;&quot;, timeoutSeconds);
            return MessageBox.Show(owner, text);
        }

        public static DialogResult Show(IWin32Window owner, string text, string caption, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(owner, text, caption);
        }

        public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(owner, text, caption, buttons);
        }

        public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(owner, text, caption, buttons, icon);
        }

        public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(owner, text, caption, buttons, icon, defButton);
        }

        public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(owner, text, caption, buttons, icon, defButton, options);
        }

        public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
        public delegate void TimerProc(IntPtr hWnd, uint uMsg, UIntPtr nIDEvent, uint dwTime);

        public const int WH_CALLWNDPROCRET = 12;
        public const int WM_DESTROY = 0x0002;
        public const int WM_INITDIALOG = 0x0110;
        public const int WM_TIMER = 0x0113;
        public const int WM_USER = 0x400;
        public const int DM_GETDEFID = WM_USER + 0;

        [DllImport(&quot;User32.dll&quot;)]
        public static extern UIntPtr SetTimer(IntPtr hWnd, UIntPtr nIDEvent, uint uElapse, TimerProc lpTimerFunc);

        [DllImport(&quot;User32.dll&quot;)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern int UnhookWindowsHookEx(IntPtr idHook);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern int GetWindowTextLength(IntPtr hWnd);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int maxLength);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern int EndDialog(IntPtr hDlg, IntPtr nResult);

        [StructLayout(LayoutKind.Sequential)]
        public struct CWPRETSTRUCT
        {
            public IntPtr lResult;
            public IntPtr lParam;
            public IntPtr wParam;
            public uint message;
            public IntPtr hwnd;
        };

        private const int TimerID = 42;
        private static HookProc hookProc;
        private static TimerProc hookTimer;
        private static uint hooktimeoutSeconds;
        private static string hookCaption;
        private static IntPtr hHook;

        static MessageBoxEx()
        {
            hookProc = new HookProc(MessageBoxHookProc);
            hookTimer = new TimerProc(MessageBoxTimerProc);
            hooktimeoutSeconds = 0;
            hookCaption = null;
            hHook = IntPtr.Zero;
        }

        private static void Setup(string caption, uint timeoutSeconds)
        {
            if (hHook != IntPtr.Zero)
                throw new NotSupportedException(&quot;multiple calls are not supported&quot;);

            hooktimeoutSeconds = timeoutSeconds*1000;
            hookCaption = caption != null ? caption : &quot;&quot;;

            //&quot;AppDomain.GetCurrentThreadId()&quot; is obsolete, however, its replacement &quot;Thread.CurrentThread.ManagedThreadId&quot; isn't correct this context.
            //See: http://stackoverflow.com/questions/772354/appdomain-getcurrentthreadid-vs-thread-managedthreadid-for-windows-api-calls
            #pragma warning disable 618 //disable the obsolete warning
            hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, hookProc, IntPtr.Zero, AppDomain.GetCurrentThreadId()); //obsolete: 
            #pragma warning restore 618 //enable the obsolete warning
        }

        private static IntPtr MessageBoxHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode &amp;amp;lt; 0)
                return CallNextHookEx(hHook, nCode, wParam, lParam);

            CWPRETSTRUCT msg = (CWPRETSTRUCT)Marshal.PtrToStructure(lParam, typeof(CWPRETSTRUCT));
            IntPtr hook = hHook;

            if (hookCaption != null &amp;amp;amp;&amp;amp;amp; msg.message == WM_INITDIALOG)
            {
                int nLength = GetWindowTextLength(msg.hwnd);
                StringBuilder text = new StringBuilder(nLength + 1);

                GetWindowText(msg.hwnd, text, text.Capacity);

                if (hookCaption == text.ToString())
                {
                    hookCaption = null;
                    SetTimer(msg.hwnd, (UIntPtr)TimerID, hooktimeoutSeconds, hookTimer);
                    UnhookWindowsHookEx(hHook);
                    hHook = IntPtr.Zero;
                }
            }

            return CallNextHookEx(hook, nCode, wParam, lParam);
        }

        private static void MessageBoxTimerProc(IntPtr hWnd, uint uMsg, UIntPtr nIDEvent, uint dwTime)
        {
            if (nIDEvent == (UIntPtr)TimerID)
            {
                short dw = (short)SendMessage(hWnd, DM_GETDEFID, IntPtr.Zero, IntPtr.Zero);

                EndDialog(hWnd, (IntPtr)dw);
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NPT.Common;

namespace WinFormsIdleTimerTest
{
    public partial class BaseForm : Form
    {
        private IdleTimer idleTimer = null;

        public BaseForm()
        {
            InitializeComponent();
        }

        protected int IdleTimeoutSeconds { get; set; }
        
        protected virtual void StartIdleTimer()
        {
            if (idleTimer == null)
            {
                StopIdleTimer();
                idleTimer = new IdleTimer(idleTimeoutSeconds: IdleTimeoutSeconds, sychronizingObject: this);
                idleTimer.IsIdle += new IdleTimer.IsIdleEventHandler(IdleTimer_IsIdle);
            }
            idleTimer.Start();
        }

        protected virtual void StopIdleTimer()
        {
            if (idleTimer != null) idleTimer.Stop();
        }

        protected virtual void IdleTimer_IsIdle(object sender, IdleTimerEventArgs e)
        {
            //handle IsIdle event, close the form (override in inherting classes to do something different)
            Close();
        }

        public new void Close()
        {
            StopIdleTimer();
            base.Close();
        }

        public new void Hide()
        {
            StopIdleTimer();
            base.Hide();
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NPT.Common;

namespace WinFormsIdleTimerTest
{
    public partial class MainForm : BaseForm
    {
        public MainForm()
        {
            InitializeComponent();
            IdleTimeoutSeconds = 5;
            StartIdleTimer();
        }

        private void CancelButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        protected override void IdleTimer_IsIdle(object sender, IdleTimerEventArgs e)
        {
            //an optional override of the BaseForm implementation to do something more than just closing the form
            //MessageBoxEx is an implementation of MessageBox that dismisses itself after a specified number of seconds
            var response = MessageBoxEx.Show(
                    &quot;Is there anybody out there?&quot;,
                    string.Format(&quot;System Idle Detected ({0} seconds)&quot;, e.IdleSeconds),
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button2,
                    10);
            if (response == System.Windows.Forms.DialogResult.No)
            {

                MessageBoxEx.Show(
                    &quot;\tGoodbye blue sky.&quot;,
                    string.Empty,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.None,
                    MessageBoxDefaultButton.Button1,
                    3);

                Close();
                return;
            }
            StartIdleTimer();
        }
    }
}</pre><p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/05/26/windows-forms-inactivity-timeout-class/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generate Unique Namespace (in DNS Name Format)</title>
		<link>http://www.elementalp.com/blog/index.php/2015/05/26/generate-unique-namespace-in-dns-name-format/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/05/26/generate-unique-namespace-in-dns-name-format/#comments</comments>
		<pubDate>Tue, 26 May 2015 20:12:07 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=100</guid>
		<description><![CDATA[[crayon-6a06f750f1eba110207568/] Generates a unique namespace that conforms to DNS name format from the input. Releated: Validate Format of a Domain Name post Input formats: If email address, the host part is used. If URI, the primary domain name is used. If neither of the above formats then uses the input as is. Looks in the [Subscription] table [&#8230;]]]></description>
				<content:encoded><![CDATA[<p></p><pre class="crayon-plain-tag">originally posted 2014-08-06</pre><p>Generates a unique namespace that conforms to DNS name format from the input.</p>
<div>
<p><a href="http://www.elementalp.com/blog/index.php/2015/05/26/validate-format-of-a-domain-name/">Releated: Validate Format of a Domain Name post</a></p>
<div>Input formats:</div>
<div>If email address, the host part is used.</div>
<div>If URI, the primary domain name is used.</div>
<div>If neither of the above formats then uses the input as is.</div>
<div>Looks in the [Subscription] table of the specified database table for the [Namespace] column to determine uniqueness.</div>
<p>&nbsp;</p><pre class="crayon-plain-tag">//LinqPad Query, Language = &quot;C# Program&quot;
void Main()
{
  string value = &quot;justin@elementalp.com&quot;;
  GenerateNamespace(value).Dump(value + &quot; becomes...&quot;);
  
  value = &quot;The ABC Company!&quot;;
  GenerateNamespace(value).Dump(value + &quot; becomes...&quot;);
  
  value = &quot;Foo&quot;;
  GenerateNamespace(value).Dump(value + &quot; becomes...&quot;);	
}

/// &amp;amp;lt;summary&amp;amp;gt;
/// Uses an input value as the basis for generating a unique namespace
/// If the formatted input name is already in use, a number will be appended to it until a unique namespace results.
/// Input value defaults to &quot;ORG&quot;
/// Output is made to confirm to DNS name requirements.
/// Examines the SQL object &quot;[npt_cloud].[dbo].[Subscription].[Namespace]&quot; to check for uniqueness.
/// &amp;amp;lt;/summary&amp;amp;gt;
public string GenerateNamespace(string value)
{

  //string value = &quot;https://this.that.these.those.elementalp.com&quot;;
  //string value = &quot;----= The-ElementalP-Company =----&quot;;
  string result = null;
  
  const string sql =
  @&quot;declare @pattern nvarchar(100) = '%[^0-9A-Za-z\-]%' --filter chars that are not alpha, numerics, or dashes
  declare @defaultName nvarchar(100) = 'ORG'; --the default namespace name
  declare @try nvarchar(100) = null

  	if(@ns is null or len(@ns)=0) goto thenext;

  --remove characters not in the pattern
  while patindex(@pattern, @ns) &amp;amp;gt; 0 set @ns = stuff(@ns, patindex(@pattern, @ns), 1, '');
  set @ns = ltrim(rtrim(@ns));
  if(@ns is null or len(@ns)=0) goto thenext;
  
  --remove leading dashes
  while (patindex('-%', @ns) = 1) set @ns = substring(@ns,2,len(@ns));
  
  --remove trailing dashes
  while (patindex('%-', @ns) = len(@ns)) set @ns = substring(@ns,1,len(@ns)-1);
  
  --shorten to 63 chars, make upper case, and trim                   
  set @ns = ltrim(rtrim(upper(substring(@ns,1,63))));
    
  thenext:
  
  --default empty namespace
  if(@ns is null or len(@ns)=0) set @ns = @defaultName  --goto theend;
    
  set @try = @ns
  
  declare @num int = 0;
  while (1=1)
  begin
    if exists (select [Namespace] from [dbo].[Subscription] where [Namespace] like @try)
    begin
      set @num = @num + 1;
      set @try = @ns + convert(nvarchar(10),@num)
    end
  else break;
  
  end
  theend:
  select [Namespace] = @try;&quot;;

  System.Diagnostics.Debug.WriteLine(string.Format(&quot;Input: {0}&quot;,  value!=null ? string.Format(&quot;\&quot;{0}\&quot;&quot;,value) : &quot;null&quot;));
    
  //parse host name from namespace
  if(!string.IsNullOrWhiteSpace(value))value = ParseNamespace(value);
  
  if(value==null) value = string.Empty;

  using (var connection = new SqlConnection(&quot;Data Source=.;Initial Catalog=npt_cloud;Application Name=npt;Integrated Security=true;&quot;))
  {
    connection.Open();
    using (var command = new SqlCommand(sql, connection))
    {
      var param = new SqlParameter(&quot;@ns&quot;, System.Data.SqlDbType.NVarChar);
      param.Value = value;
      command.Parameters.Add(param);
    
      result = command.ExecuteScalar() as string;
      connection.Close();
      return result;
    }
  }
}

/// &amp;amp;lt;summary&amp;amp;gt;
/// Parses a namespace from input value.
/// If the input value is an email address, the output will be the host name.
/// If the input value is a URL, the output is the primary domain name.
/// If the input value is not one of the above formats, the input text before the first period (if any) is returned.
/// &amp;amp;lt;/summary&amp;amp;gt;
public static string ParseNamespace(string text)
{
  string ns = null;
  try
  {
      //try get domain as email address
      var addr = new MailAddress(text);
      ns = addr.Host;
  }
  catch (System.FormatException ex1)
  {
      try
      {
          //try get domain as uri
          var uri = new Uri(text);
          string[] hostParts = uri.Host.Split(new string[1] { &quot;.&quot; }, StringSplitOptions.RemoveEmptyEntries);
          ns = hostParts[hostParts.Length-2];
      }
      catch (System.UriFormatException ex2)
      {
          //use id as the domain
          ns = text;
      }
  }

  if (ns != null) ns = ns.Split(new char[] { '.' }, 2)[0];
  
  return ns;
}</pre><p>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/05/26/generate-unique-namespace-in-dns-name-format/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Get SQL Server Version Info</title>
		<link>http://www.elementalp.com/blog/index.php/2015/05/26/get-sql-server-version-info/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/05/26/get-sql-server-version-info/#comments</comments>
		<pubDate>Tue, 26 May 2015 16:39:14 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=89</guid>
		<description><![CDATA[[crayon-6a06f750f29e9784172712/] [crayon-6a06f750f2a6c505657884/]]]></description>
				<content:encoded><![CDATA[<p></p><pre class="crayon-plain-tag">originally posted 2015-01-06</pre><p></p>
<p></p><pre class="crayon-plain-tag">select 
[Product] = convert(nvarchar(25),
  case when [Version] like '12.%' then 'SQL Server 2014'
  when [Version] like '11.%' then 'SQL Server 2012'
  when [Version] like '10.50%' then 'SQL Server 2008 R2'
  when [Version] like '10.%' then 'SQL Server 2008'
  when [Version] like '9.%' then 'SQL Server 2005'
  when [Version] like '8.%' then 'SQL Server 2000'
  else 'Unknown'
  end)
,[Version]
,[VersionMajor] = convert(int, left([Version], charindex('.', [Version], 0)-1))
,[VersionInfo] = @@version
,[Level]
,[Edition]
,[BackupCompression] = convert(bit,
  case when [Version] like '12.%' and ([Edition] like '%enterprise%' or [Edition] like '%intelligence%' or [Edition] like '%standard%') then 1 --2014
  when [Version] like '11.%' and ([Edition] like '%enterprise%' or [Edition] like '%intelligence%' or [Edition] like '%standard%') then 1 --2012
  when [Version] like '10.%' and [Edition] like '%enterprise%' then 1 --2008
  else 0
  end)
from 
(
  select 
  [Version] = convert(sysname,serverproperty('ProductVersion'))
  ,[Level] = convert(sysname,serverproperty ('productlevel'))
  ,[Edition] =  convert(sysname,serverproperty ('edition'))
) as v</pre><p></p>
<p><a href="http://www.elementalp.com/blog/wp-content/uploads/2015/05/SQLServerVersionQueryOutput.png"><img src="http://www.elementalp.com/blog/wp-content/uploads/2015/05/SQLServerVersionQueryOutput.png" alt="SQLServerVersionQueryOutput" width="867" height="44" class="alignnone size-full wp-image-90" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/05/26/get-sql-server-version-info/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Determine if a path is a UNC</title>
		<link>http://www.elementalp.com/blog/index.php/2015/05/26/determine-if-a-path-is-a-unc/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/05/26/determine-if-a-path-is-a-unc/#comments</comments>
		<pubDate>Tue, 26 May 2015 16:23:22 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=75</guid>
		<description><![CDATA[[crayon-6a06f750f33ec446690198/] [crayon-6a06f750f3483751542794/]]]></description>
				<content:encoded><![CDATA[<p></p><pre class="crayon-plain-tag">originally posted 2015-02-05</pre><p></p><pre class="crayon-plain-tag">//determines if a path is a UNC path
[DllImport(&quot;shlwapi.dll&quot;, CharSet = CharSet.Unicode)]
[ResourceExposure(ResourceScope.None)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern bool PathIsUNC(
[MarshalAsAttribute(UnmanagedType.LPWStr), In] string pszPath);</pre><p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/05/26/determine-if-a-path-is-a-unc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Removing files from ClickOnce application manifest</title>
		<link>http://www.elementalp.com/blog/index.php/2015/05/26/removing-files-from-clickonce-application-manifest/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/05/26/removing-files-from-clickonce-application-manifest/#comments</comments>
		<pubDate>Tue, 26 May 2015 16:15:05 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=67</guid>
		<description><![CDATA[[crayon-6a06f750f3cb2955110379/] We have a ClickOnce application for which we are merging and/or embedding all of our dependency assemblies into a single assembly and obfuscating with Red Gate&#8217;s SmartAssembly. ClickOnce doesn&#8217;t know about the merging and embedding, so it includes the non-obfuscated individual assembly files when it publishes. It turns out that it&#8217;s easy to exclude [&#8230;]]]></description>
				<content:encoded><![CDATA[<p></p><pre class="crayon-plain-tag">originally posted 2015-02-05</pre><p>We have a ClickOnce application for which we are merging and/or embedding all of our dependency assemblies into a single assembly and obfuscating with Red Gate&#8217;s SmartAssembly. ClickOnce doesn&#8217;t know about the merging and embedding, so it includes the non-obfuscated individual assembly files when it publishes. It turns out that it&#8217;s easy to exclude these files from the deployment at publish-time from Visual Studio.</p>
<p>From Project properties &#8230;<br />
Publish tab &#8230;<br />
Application Files button &#8230;<br />
Select &#8220;Exclude&#8221; for the Publish Status of the desired files &#8230;<br />
Save project &#8230;<br />
Publish.</p>
<p>To do this to an already-published ClickOnce application requires more work. Here&#8217;s a LINQPad script example to programmatically find a file, remove it and re-sign the appropriate files.</p><pre class="crayon-plain-tag">/*
Written with LINQPad 
Programmatically remove files from a published ClickOnce application
using System.Diagnostics;
using System.IO;
using System.Xml;
*/

string sourceDir = @&quot;C:\published\my_app_1_0_0_135\&quot;;
string manifestFilePath = sourceDir + @&quot;\my_app.exe.manifest&quot;;
string applicationManifestFilePath = sourceDir + @&quot;\my_app.application&quot;;
string mageFilePath = @&quot;C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\mage.exe&quot;;
string certFilePath = @&quot;C:\certificates\MyAuthenticodeCertificate.pfx&quot;;
string certPassword = &quot;foo&quot;;

//load .manifest XML
var doc = XDocument.Load(manifestFilePath);

//rename the files w/o the .deploy extension
string[] filePaths = Directory.GetFiles(sourceDir,&quot;*.deploy&quot;);
foreach(string filePath in filePaths)
{
  string realName = filePath.Replace(&quot;.deploy&quot;,string.Empty);
  File.Move(filePath,realName);
  File.Delete(filePath);
}

//locate and remove the desired entry (e.g. the &quot;MyComponentToRemove.dll&quot; of dependency type of &quot;install&quot;)
XNamespace ns = &quot;urn:schemas-microsoft-com:asm.v2&quot;;
doc.Descendants(ns + &quot;dependentAssembly&quot;)
   .Where(x =&amp;amp;gt; (string)x.Attribute(&quot;dependencyType&quot;) == &quot;install&quot;)
   .Where(x=&amp;amp;gt; ((string)x.Attribute(&quot;codebase&quot;)).Equals(&quot;MyComponentToRemove.dll&quot;))
   .Select(x =&amp;amp;gt; x.Parent)
   .Remove();
 
//save .manifest XML
doc.Save(manifestFilePath);
 
//re-sign .manifest
Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = mageFilePath;
startInfo.Arguments = string.Format(&quot;-update \&quot;{0}\&quot; -cf \&quot;{1}\&quot; -pwd \&quot;{2}\&quot;&quot;,manifestFilePath,certFilePath,certPassword);
process.StartInfo = startInfo;
process.Start();

//re-sign .application
process = new System.Diagnostics.Process();
startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = mageFilePath;
startInfo.Arguments = string.Format(&quot;-update \&quot;{0}\&quot; -appmanifest \&quot;{1}\&quot; -cf \&quot;{2}\&quot; -pwd \&quot;{3}\&quot;&quot;,applicationManifestFilePath,manifestFilePath,certFilePath,certPassword);
process.StartInfo = startInfo;
process.Start();

//rename files with .deploy extension
foreach(string filePath in filePaths)
{
  string realName = filePath.Replace(&quot;.deploy&quot;,string.Empty);
  File.Move(realName,filePath);
  File.Delete(realName);
}</pre><p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/05/26/removing-files-from-clickonce-application-manifest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
