Wednesday, July 31, 2013

manage static state in Global.asax.cs

Following upon this, I found myself wondering if static state will persist across the changing of "pages" in a stateless web application. It turns out that it will! If you have something like so managing a counter...

namespace MvcApplication.Models
{
   public static class Counter
   {
      public static int Count;
   }
}

 
 

...the counter will grow (without getting confused or resetting) as you switch back and forth between two actions in a controller (in an ASP.NET MVC4 Web API application with C# in this case) as seen here:

using System.Web.Mvc;
using MvcApplication.Models;
namespace MvcApplication.Controllers
{
   public class HomeController : Controller
   {
      public ActionResult Index()
      {
         return View(++Counter.Count);
      }
      
      public ActionResult About()
      {
         return View(++Counter.Count);
      }
   }
}

 
 

We can drive the upfront assignment of our counter from Global.asax.cs like so:

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using MvcApplication.Models;
namespace MvcApplication
{
   public class WebApiApplication : System.Web.HttpApplication
   {
      protected void Application_Start()
      {
         Counter.Count = 0;
         AreaRegistration.RegisterAllAreas();
         WebApiConfig.Register(GlobalConfiguration.Configuration);
         FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
         RouteConfig.RegisterRoutes(RouteTable.Routes);
         BundleConfig.RegisterBundles(BundleTable.Bundles);
      }
   }
}

 
 

When I did this in Cassini I noticed that I could open two different browsers and the two browsers together would affect each other's counters and bias each others numbers. (They both dogpiled onto the counter.) Also, I noticed that if I closed all browsers, stopped the application, and restarted it, the the counter did not reset to zero. Only restarting Visual Studio allowed for a reset back to zero. This seemed imperfect so I tried this instead:

using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using MvcApplication.Models;
namespace MvcApplication
{
   public class WebApiApplication : System.Web.HttpApplication
   {
      protected void Application_Start()
      {
         AreaRegistration.RegisterAllAreas();
         WebApiConfig.Register(GlobalConfiguration.Configuration);
         FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
         RouteConfig.RegisterRoutes(RouteTable.Routes);
         BundleConfig.RegisterBundles(BundleTable.Bundles);
      }
      
      protected void Session_Start()
      {
         Counter.Count = 0;
      }
   }
}

 
 

Well, this got rid of the need to restart the application. I was able to just close all browsers to set the counter back to zero. However, different browsers still shared state! I then remembered I was using Cassini which only has one session. I switched to using IIS and the counter then only incremented based on browser session as desired!

Tuesday, July 30, 2013

a ref variable may create a situation where the compiler complains it may not be instantiated but this will never happen with an out variable

I learned this tonight.

I learned today that the unemployment rate for Austin tech workers is 0.4%!

Nice.

how to configure smtp4dev

This tells you the must haves for using this:

  1. at smtp4dev: click on the "Options" button, navigate to the "server" tab and therein set the "Domain Name" setting to be the name of your PC
  2. send fake mail messages to a fake SMTP that is the name of your PC
  3. you should be able to talk to yourself and get messages in smtp4dev queue

Turn on log4net's internal logging.

Per midpage in this, you will need something like so in App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <startup/>
   <appSettings>
      <add key="log4net.Internal.Debug" value="true"/>
   </appSettings>
   <system.diagnostics>
      <trace autoflush="true">
         <listeners>
            <add name="textWriterTraceListener"
                  type="System.Diagnostics.TextWriterTraceListener"
                  initializeData="C:\temp\log4net.txt" />
         </listeners>
      </trace>
   </system.diagnostics>
</configuration>

smtp4dev is a dummy SMTP server

get it at http://smtp4dev.codeplex.com/

Monday, July 29, 2013

Assembly generation failed -- Referenced assembly 'log4net' does not have a strong name

Fix error messages like this by signing the assembly.

of making a copy of a .dll to a second spot with Visual Studio

If you copy a Visual Studio project form one local to another you may get a 9009 error if you have a Build Events post-build event command line script (right-click on the project and pick Properties and then go to the Build Events tab to see these) which tries to make a copy of the .dll for the project's compilation to a second locale and can no longer find the second locale. Such a script might look like so:

"$(ProjectDir)..\post-build.bat" "$(ProjectName)" "$(ProjectDir)" "$(TargetDir)" "$(TargetName)"

Debug supporting projects within a WinForms solution without having the source code for the solution!

If multiple WinForms apps use common .dlls (projects inside Visual Studio solutions) and you would like to do the "attach to process" trick while running one WinForm app to look into a .dll kept in another project within a different solution where a WinForm project serves as the UI project, you may still do so. Again, this assumes you are not debugging the UI WinForms project, but a common second project. Start by putting the following line of C# in a spot in code you know will get hit in the common-across-two-solutions project:

Thread.Sleep(30000);

 
 

Rebuild the solution. Put a copy of the appropriate .dll in the bin folder of the WinFroms application you are to run. Set a breakpoint to hit back in the project in Visual Studio. Open "Component Services" and drill down to: Console Root > Component Services > Computers > My Computer > COM+ Applications ...select COM+ Applications and then pick "Status" from the "View" menu at the top navigation. This should allow you to see a few columns including "PID" which is vital for this process. Run the WinForms app and wait for a new line item to appear in the list here. Note the PID and then in Visual Studio pick "Attack to Process..." from "Tools" and find the item to attach to*. The ID at Visual Studio will match up to the PID at Component Services.

*check the checkbox for: Show processes for all users

Apache's web presence for log4net

At http://logging.apache.org/log4net/:

Sunday, July 28, 2013

Implement an Interface in C#

When you inherit from an interface in C# it is appropriate to say you implement the interface instead of inheriting from it.

Friday, July 26, 2013

I saw Robert Birch speak on using SQL in financial domains last night.

The setting was at Sharon Cichelli's Polyglot Programmers coding circle. The big new thing I learned about SQL that I did not know was that it was started in 1974 (the year I was born) at IBM (where my Mom worked) by Donald D. Chamberlin and Raymond F. Boyce! Interesting domain-specific stuff:
  • In comparing zip code ranges to incomes via SQL, an institution was able to home in on selective mortgages which were ideal to purchase.
  • ROA (Return on Assets) is Income divided by Assets at a balance sheet. A company with an ROA of more than 7% would be good to invest in. Those guys are on their way to taking over the world.
  • The ratio of Equity to Assets is a good to track. A ranking of 7, for example, implies that the organization holds 7 times more assets than debt.
  • A Market Cap is a dollar figure denoting what it would require to buy out enough of a public company to take it private. Companies with small Market Caps are typically blossoming and may offer the opportunity for up to 20% growth in contrast to a company such as IBM for which one should not hold one's breath for a double digit number.

Thursday, July 25, 2013

How are using statements in C# like out and ref variables?

First a bit of a set up. I made an ASP.NET MVC 4 Web API application in Visual Studio 2012 and I made the default /home/index/ view look like so:

@using System.Data
@model DataSet[]
@foreach (DataSet set in Model)
{
   foreach (DataRow row in set.Tables[0].Rows)
   {
      var copy = row[2];
      <hr style="margin-top: 80px;" />
      <text>@copy</text>
   }
}

 
 

I then made HomeController look like so:

using System.Data;
using System.Web.Mvc;
using FeelSoUsed.DataIntegration;
namespace FeelSoUsed.Controllers
{
   public class HomeController : Controller
   {
      public ActionResult Index()
      {
         Repository repository = new Repository();
         DataSet[] dataSets = repository.GetStuff();
         return View(dataSets);
      }
   }
}

 
 

I suppose I could have skipped mentioning the stuff above, but here is where things get really interesting:

using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace FeelSoUsed.DataIntegration
{
   public class Repository
   {
      public DataSet[] GetStuff()
      {
         string specs = ConfigurationManager.ConnectionStrings["x"].ConnectionString;
         using (SqlConnection connection = new SqlConnection(specs))
         {
            Query query = new Query();
            DataSet firstSet = query.GetStuff(connection);
            DataSet secondSet = query.GetStuff(connection);
            return new DataSet[] {firstSet, secondSet};
         }
      }
   }
}

 
 

The Query class looks like this:

using System.Data;
using System.Data.SqlClient;
namespace FeelSoUsed.DataIntegration
{
   public class Query
   {
      public DataSet GetStuff(SqlConnection connection)
      {
         using (SqlCommand command = new SqlCommand())
         {
            using (SqlDataAdapter adapter = new SqlDataAdapter())
            {
               DataSet dataSet = new DataSet();
               string query = "dbo.GetStuff";
               command.CommandText = query;
               command.CommandType = CommandType.StoredProcedure;
               command.Connection = connection;
               adapter.SelectCommand = command;
               adapter.Fill(dataSet);
               return dataSet;
            }
         }
      }
   }
}

 
 

The thing to see here is that from within a using statement, one may hand the star of the using statement into another method and the star's behavior goes unchanged... well, up to a point. For example if Query were changed to be like so:

using System.Data;
using System.Data.SqlClient;
namespace FeelSoUsed.DataIntegration
{
   public class Query
   {
      public DataSet GetStuff(SqlConnection connection)
      {
         using (connection)
         {
            using (SqlCommand command = new SqlCommand())
            {
               using (SqlDataAdapter adapter = new SqlDataAdapter())
               {
                  DataSet dataSet = new DataSet();
                  string query = "dbo.GetStuff";
                  command.CommandText = query;
                  command.CommandType = CommandType.StoredProcedure;
                  command.Connection = connection;
                  adapter.SelectCommand = command;
                  adapter.Fill(dataSet);
                  return dataSet;
               }
            }
         }
      }
   }
}

 
 

Well... after Repository runs the code in Query a first time, the Dispose method on the SqlConnection instance will be run doing away with it. This is so in the second scenario as another using statement is nested in the second version of Query for the variable that is handed into it. However, you shouldn't do this sort of thing if you haven't made the "using object" immediately in a given method as the "state" of the SqlConnection being disposed will bubble back out of the method to the Repository method calling it and affect the "state" of the GetStuff() method in Repository. This is how a variable that is the star of a using statement may behave akin to an out or ref variable. The second call to Query in Repository cannot run in this circumstance because the SqlConnection will have been disposed of by the first Query instance!

Define where log4net writes files to from C#.

You may override the log4net.config specs for writing logs from code as seen below. In this example we override where the log gets written to and what its name is:

log4net.Repository.Hierarchy.Hierarchy hierarchy = LogManager.GetLoggerRepository()
      as log4net.Repository.Hierarchy.Hierarchy;
RollingFileAppender appender = (RollingFileAppender)hierarchy.GetAppenders()
      .Where(x => x.GetType() == typeof(RollingFileAppender)).FirstOrDefault();
string filePathToLogTo = "c:\myfolder\whatever.log";
appender.File = filePathToLogTo;
appender.ActivateOptions();

 
 

While I am thinking of it there is something to be wary of in this code. Somewhere upstream you will have something like so:

var fileInfo = new FileInfo("c:\something\log4net.config");
XmlConfigurator.Configure(fileInfo);

 
 

If the config file is not found at the path specified, then hierarchy.GetAppenders() will return an empty array and you will get an opague error message. That goes for this too. If this is happening to you, just make sure that your config file exists. I know this is hard to troubleshoot. Visual Studio will put a squiggly blue line under appender.File warning you that appender could be null either way, but honestly if it is null it is going to be because you cannot find the config file.

Make log4net write logs to a particular folder instead of the immediate bin folder.

Change out the follow bit of log4net.config as seen in the third blob of code here to specify a specific path like so:

<file value="c:\errorlog.log" />

 
 

I think the c needs to be lowercase and not an uppercase C. This learned this the hard way. (silent failures) Grrr.

Wednesday, July 24, 2013

Ask a question of the Dojo Community.

At: http://dojotoolkit.org/community/

(then wait for an answer)

The best way to find all matches for a string of text in Visual Studio 2012...

...is to press Ctrl-F (find) or Ctrl-H (find and replace) while at least one file is open to bring up a dialog box like so:

then...

  1. type something to find in the topmost fill-in-the-blank field
  2. click the small down arrow at the right of the larger rightwards-pointing arrow
  3. pick "Find All" from the small menu which appears

You probably will want to tweak some of the other settings in the dialog box too such as whether or not you search the Entire Solution or just the immediate file. The results will come back in a list wherein you may click any one result to bring up the file associated in the IDE.

Tuesday, July 23, 2013

Destroy everything after a certain changeset in Mercurial/TortoiseHG.

If you are an administrator you may do this. Go the settings for a repository in FogBugz Kiln and then go to "Strip Changeset" where you will put in the changeset number to keep. Everything downstream gets the axe.

Override the log4net.config specifications for sending emails from C#.

My boss found this and this and concluded that these settings may be superseded splendidly from within code. He was right! Observe:

log4net.Repository.Hierarchy.Hierarchy hierarchy = log4net.LogManager.
      GetLoggerRepository() as log4net.Repository.Hierarchy.Hierarchy;
log4net.Appender.SmtpAppender appender = (log4net.Appender.SmtpAppender)
      hierarchy.GetAppenders().Where(x => x.GetType() == typeof(log4net.Appender.
      SmtpAppender)).FirstOrDefault();
appender.Subject = "maybe THIS will get your attention";
appender.ActivateOptions();

 
 

This just has to happen somewhere upstream of log4net logging attempts.

Hand a parameter at a constructor's signature to a base class in C#.

namespace Whatever
{
   public class Chihuahua : Dog
   {
      protected Chihuahua(List<Flea> fleas) : base(fleas)
      {
         
//do something here
      }
   }
}

 
 

If the base class does not have a parameterless constructor you will be have to do something like this to have a new class inherit from the base class.

Sunday, July 21, 2013

This isn't so good guys.

I don't know what you were trying to do with the random number in the ebRand variable, but you probably didn't intend to have its assignment bubble up to the screen just below the two buttons at the base of visConfirmation.aspx. At least you are using C#. Kudos.

Friday, July 19, 2013

yfrog is throwing away some of the images I pushed to it

yfrog has gone the way of twitpic to become a no-longer-cool place to host images.

casting a DateTime to a string in C#

dt.ToString("yyyy-MM-dd");

Is an example per this. While this suggests the hours, minutes, seconds, milliseconds, and antemeridian-versus-postmeridian stuff may be expressed like:

dt.ToString("hh:mm:ss.fff tt");

Rethrow an exception in a C# catch block.

try
{
   DoSomething();
}
catch (Exception exception)
{
   log.Fatal("Oh no!", exception);
   throw;
}

The unassigned state for a DateTime type in C# is not equivalent to null as I had hoped.

The first two asserts in this test will fail:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Whatever.Test
{
   [TestClass]
   public class UnitTest
   {
      private DateTime foo;
      
      [TestMethod]
      public void TestMethod()
      {
         Assert.AreEqual(foo, null);
         DateTime? bar = foo;
         Assert.AreEqual(bar, null);
         foo = new DateTime(1974,8,24);
         bar = foo;
         Assert.AreNotEqual(bar, null);
         Assert.AreEqual(bar, new DateTime(1974, 8, 24));
      }
   }
}

 
 

This test passes:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Whatever.Test
{
   [TestClass]
   public class UnitTest
   {
      private DateTime foo;
      
      [TestMethod]
      public void TestMethod()
      {
         Assert.AreEqual(foo, new DateTime(0001, 1, 1));
         DateTime? bar = foo;
         Assert.AreEqual(bar, new DateTime(0001, 1, 1));
         foo = new DateTime(1974,8,24);
         bar = foo;
         Assert.AreNotEqual(bar, null);
         Assert.AreEqual(bar, new DateTime(1974, 8, 24));
      }
   }
}

Thursday, July 18, 2013

log4net email alerts

An appender such as the one below will allow one to send email alerts from log4net.

<appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
   <authentication value="Basic" />
   <to value="tomjaeschke@tomjaeschke.com,fevercheese@gmail.com" />
   <from value="tjaeschke@example.com" />
   <username value="tjaeschke@example.com" />
   <password value="b0x1ng_Helena" />
   <subject value="Notification" />
   <smtpHost value="smtp.example.com" />
   <bufferSize value="1" />
   <lossy value="true" />
   <evaluator type="log4net.Core.LevelEvaluator">
      <threshold value="FATAL"/>
   </evaluator>
   <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="Something went wrong." />
   </layout>
</appender>

Using the log4net.dll isn't too tough.

using System;
namespace Whatever
{
   public class Calculator
   {
      public string Calculate(string ying, string yang)
      {
         decimal Ying = Convert.ToDecimal(ying);
         decimal Yang = Convert.ToDecimal(yang);
         decimal calulation = Ying + Yang;
         return calulation.ToString();
      }
   }
}

 
 

...may be made a bit safer like so:

using System;
using System.IO;
using log4net;
using log4net.Config;
namespace Whatever
{
   public class Calculator
   {
      public string Calculate(string ying, string yang)
      {
         var f = new FileInfo(Directory.GetCurrentDirectory() + "\\log4net.config");
         XmlConfigurator.Configure(f);
         ILog log = LogManager.GetLogger(typeof(Calculator));
         decimal Ying = 0m;
         decimal Yang = 0m;
         try
         {
            Ying = Convert.ToDecimal(ying);
            Yang = Convert.ToDecimal(yang);
         }
         catch (Exception ex)
         {
            log.Fatal(ex);
         }
         decimal calulation = Ying + Yang;
         return calulation.ToString();
      }
   }
}

 
 

Clearly log4net.config is important and we will go fishing for it in bin/Debug or bin/Release so it will need, in a Visual Studio project, a Build Action of "Content" and Copy To Output Directory setting of "Copy always" or at least "Copy if newer" to make it findable/readable. The config file looks like this:

<log4net>
   <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
      <file value="error.log" />
      <appendToFile value="true" />
      <maximumFileSize value="100KB" />
      <maxSizeRollBackups value="2" />      
      <layout type="log4net.Layout.PatternLayout">
         <conversionPattern value="%d{HH:mm:ss} %-5p %c - %message
               %property{adapterName}%newline" />
      </layout>
   </appender>   
   <root>
      <level value="FATAL" />
      <appender-ref ref="RollingFile" />
   </root>
</log4net>

 
 

error.log also gets written to bin/Debug or bin/Release. An entry looks like so:

14:38:13 FATAL Whatever.Calculator - System.FormatException: Input string was not in a
      correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer&
         number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseDecimal(String value, NumberStyles options,
         NumberFormatInfo numfmt)
   at System.Convert.ToDecimal(String value)
   at Whatever.Calculator.Calculate(String ying, String yang) in
         c:\apps\log4net\Whatever\Whatever\Calculator.cs:line 23 (null)

I'm going to try to teach myself log4net logging today.

Links to help:
  1. http://handcraftsman.wordpress.com/2011/06/30/making-log4net-smtpappender-work-with-gmail/
  2. http://www.codeproject.com/Articles/140911/log4net-Tutorial
  3. http://stackoverflow.com/questions/10384920/send-an-email-when-an-error-occurs
  4. http://www.beefycode.com/post/Log4Net-Recommended-Practices-pt-1-Your-Code.aspx
  5. http://david.gardiner.net.au/2008/11/log4nets-smtpappender-with-multiple.html
  6. http://stackoverflow.com/questions/15523613/log4net-smtp-appender-not-sending-emails

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;

is superior to...

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit;

 
 

or certianly the default...

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

 
 

...in the name of getting fonts to display at consistent sizes within a WinForms form. The font size may contort otherwise when one changes this display setting:

...which is found by right-clicking on the Desktop in Windows 7 and picking "Personalize" and then clicking the "Display" link at the dialog box which appears.

Wednesday, July 17, 2013

Is it immoral to use a KeyValuePair like a Tuple in C#?

An Array is sort of like a pill packet of Sudafed in that everything contained in the collection is of the same type as defined by the collection itself. In a pack of Sudafed all of the pills will be Sudafed pills. But what if you need to take different sorts of pills (not necessarily a bad reflection upon you) and yet you want to keep all of your pills contained together. Well, those plastic containers for the seven different days of the week seem pretty cool for that.

With such a container one could keep up to seven different pills separate in a greater collection. In a Tuple one may keep up to seven different objects of any type together so the Tuple matches up to a pill box in my analogy. The Tuple is really handy in C# for handing more than one thing back from a method which will only technically return one thing. This hacky way of beating the Thunderdome problem has always seemed a lot cleaner to me than using ref and out variables, and I have fallen in love with Tuples. However, today I was told I had to downgrade a WinForms app I recently made in ASP.NET 4.5 to run in ASP.NET 3.5. When I did so I found I could not use a Tuple so I put my pills in my contact lens case instead.

If you think about when you use Tuples, you may realize that majority of the time you are making a Tuple that holds two things in lieu of three to seven things. I have never needed a Tuple that is seven items in size, but I use Tuples that are two items long all the time. (Example: I want to hand back from my method the ideal output of whatever type and a placeholder for a string value for an exception error message which could arise within the method.) If you are like me you are experiencing the same thing: Tuples with fewer items come out in your code more frequently than Tuples with more items. This means that probably more often than not, you may "use Tuples" in older versions of C# by just using a KeyValuePair type in lieu of a Tuple type. This is NOT what a KeyValuePair is intended for and you may only store up to two items in a KeyValuePair in lieu of up to seven, but:

  1. it works
  2. you only need two slots most of the time

Is this a dirty hack? Well consider this question: Are Tuples themselves a dirty hack and is this any worse?

unus, una, unum

Latin-1 is the flavor of unicode most akin in form to the 128 token ASCII characters.

LogicLib

LogicLib apparently allows NSIS to do looping, for/while stuff, and nested if statements which it does not otherwise support.

Set a WinForm's FormBorderStyle property to FixedSingle to keep users from dragging its edge to a different size.

Not doing so is tacky.

Solarized

...is a recommended color scheme!

Snipping Tool

...is something new as of Windows 7 which makes screen grabs a little less painful. Just type "snip" at the start menu to get it. When it appears pick "Rectangular Snip" from the "New" menu and then drag a rectangular area around the piece of the screen you wish to capture. After you drag, you will be able to save the image. This is a little bit easier than pressing Windows-PrtScn or some other combination with PrtScn and then going into Paint to do a Ctrl-V.

Tuesday, July 16, 2013

Query Analyzer 3.5

...is a tool that will allow you to run SQL against SQL Server Compact Edition Database Files (.sdf). On a handheld device, click the icon that looks like a yellow database cylinder with a green right-pointing arrow overlaying it to make a new database connection. Then navigate to the "SQL" tab to run SQL commands such as this one for adding an index to a datetime type column:

CREATE INDEX Order_13 ON Order (CreationDate);

SQL Server 2008 Service Pack 3

You need SQL Server 2008 Service Pack 3 for the Database Engine Tuning Advisor to behave well. Wait! This is a lie. The service pack didn't help me at all. I am getting results different from that of my boss. What gives? I hoped I was just missing the service pack. Grrr.

Select @@version

...as a query in SSMS gave me:

Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (X64) Jul 9 2008 14:17:44 Copyright (c) 1988-2008 Microsoft Corporation Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)

Display Estimated Execution Plan is for big queries and little resources.

The following assumes MSSQL 2008: This expos the difference between "Display Estimated Execution Plan" which is really something to run when you can't afford to run a query because it is too big, and the much more accurate (as it is not an estimate) "Include Actual Execution Plan" which will include a tab within the query results called "Execution plan" that shows a comparable breakdown of the expense of the various bits of a query. If you have "Include Actual Execution Plan" toggled on when you run a query in SSMS you get the extra tab. The video shows using it by running a bunch of queries that are nearly identical save for some experimental tweaks at once to see how they all vary in bringing back "Display Estimated Execution Plan" flows. You can't use “Display Estimated Execution Plan” in SQL Server Express or SQL Server Compact Edition as best as I can tell, so therein you have to just use "Display Estimated Execution Plan."

Monday, July 15, 2013

You may need to boost memory allocation in the Database Engine Tuning Advisor.

The minimum storage space required for the selected physical design structures exceeds the default storage space selected by Database Engine Tuning Advisor. Either keep fewer physical design structures, or increase the default storage space to be larger than at least 2 MB. Use one of the following methods to increase storage space: (1) If you are using the graphical user interface, enter the required value for Define max. space for recommendations (MB) in the Advanced Options of the Tuning Options tabbed page; (2) If you are using dta.exe specify the maximum space value for the –B argument; (3) If you are using an XML input file, specify the maximum space value for the <StorageBoundInMB> element under <TuningOptions>

...is an error one might see when trying to analyze a query in the "Database Engine Tuning Advisor" which is a thing that you may have as a part of your Microsoft SQL Server install. The cure:

  1. go to the "Tuning Options" tab
  2. click "Advanced Options..."
  3. check the checkbox by "Define max. space for recommendations (MB):"
  4. type some big number like 200 into the fill-in-the-blank box at the upper right of the "Advanced Tuning Options" dialog box
  5. click "OK"

Device Emulator Manager shortcut!

Make a shortcut to...

C:\Program Files (x86)\Microsoft Device Emulator\1.0\dvcemumanager.exe

...so that you may open the "Device Emulator Manager" without having to go into Visual Studio 2008 to do so.

Sunday, July 14, 2013

What PLINQ can't do!

PLINQ per both common sense and the copy in C# 4.0 in a Nutshell is not going to help optimize database queries so it won't help with this challenge for example.

Make a Timespan to inspect the duration of a code loop?

DateTime beforeProcess = DateTime.Now;
//imagine a LINQ process here
DateTime afterProcess = DateTime.Now;
TimeSpan duration = afterProcess.Subtract(beforeProcess);
//imagine setting a breakpoint here to inspect duration

 
 

This touches on the Timespan type some. In setting a breakpoint one could inspect the Timespan and see how many milliseconds an execution took. Something that might be easier to read is:

long duration = (afterProcess - beforeProcess).Ticks;

 
 

It is really up to you. Run a code loop a couple of times and you may see different results with the timing getting faster for a few times until it finds a "floor."

Saturday, July 13, 2013

See what Entity Framework is doing beneath the hood with SQL Server Profiler.

Imagine one were to query from Entity Framework and then cast the results to a series of regular C# objects such as this one:

namespace OldSchool.Models
{
   public class Dto
   {
      public string Foo { get; set; }
      public string Bar { get; set; }
      public string Baz { get; set; }
      public string Qux { get; set; }
   }
}

 
 

I have a friend who is facing the prospect of trying to optimize code that does just that. Code like so:

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using OldSchool.Models;
namespace OldSchool.Controllers
{
   public class HomeController : Controller
   {
      public ActionResult Index()
      {
         using (RepoEntities myStuff = new RepoEntities())
         {
            List<Dto> myGunk = (from a in myStuff.Yangs join i in myStuff.Yings on a.YingId
                  equals i.YingId select new Dto()
               {
                  Foo = i.foo,
                  Bar = a.bar,
                  Baz = a.baz,
                  Qux = a.qux
               }).ToList();
            return View(myGunk);
         }
      }
   }
}

 
 

In the name of trying to figure out how to optimize, it is probably best to spy on the SQL generated with SQL Server Profiler like so:

 
 

There is one query:

SELECT
1 AS [C1],
[Extent2].[foo] AS [foo],
[Extent1].[bar] AS [bar],
[Extent1].[baz] AS [baz],
[Extent1].[qux] AS [qux]
FROM [dbo].[Yang] AS [Extent1]
INNER JOIN [dbo].[Ying] AS [Extent2] ON [Extent1].[YingId] = [Extent2].[YingId]

 
 

Well, is there even anything to change here? There is not much to vary while having the same outcome. Things I can think to try are:

  1. taking the casting to the intermediate object out of the same line of code that does the query
  2. getting rid of the join
  3. both things at once

 
 

The first alteration...

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using OldSchool.Models;
namespace OldSchool.Controllers
{
   public class HomeController : Controller
   {
      public ActionResult Index()
      {
         using (RepoEntities myStuff = new RepoEntities())
         {
            var y = from a in myStuff.Yangs join i in myStuff.Yings on a.YingId equals i.YingId
                  select a;
            List<Dto> myGunk = new List<Dto>();
            foreach (Yang a in y)
            {
               myGunk.Add(new Dto()
               {
                  Foo = a.Ying.foo,
                  Bar = a.bar,
                  Baz = a.baz,
                  Qux = a.qux
               });
            }
            return View(myGunk);
         }
      }
   }
}

 
 

...just makes things worse. Look, we have an n+1 problem by which I mean a separate query is run for every child referenced by a parent collection. Observe:

  • SELECT
    [Extent1].[YangId] AS [YangId],
    [Extent1].[bar] AS [bar],
    [Extent1].[baz] AS [baz],
    [Extent1].[qux] AS [qux],
    [Extent1].[YingId] AS [YingId]
    FROM [dbo].[Yang] AS [Extent1]
     
  • exec sp_executesql N'SELECT
    [Extent1].[YingId] AS [YingId],
    [Extent1].[foo] AS [foo]
    FROM [dbo].[Ying] AS [Extent1]
    WHERE [Extent1].[YingId] = @EntityKeyValue1',N'@EntityKeyValue1
          uniqueidentifier',@EntityKeyValue1='B1AD1D61-C399-4235-A072-
          A8D98BCD11AC'
     
  • exec sp_executesql N'SELECT
    [Extent1].[YingId] AS [YingId],
    [Extent1].[foo] AS [foo]
    FROM [dbo].[Ying] AS [Extent1]
    WHERE [Extent1].[YingId] = @EntityKeyValue1',N'@EntityKeyValue1
          uniqueidentifier',@EntityKeyValue1='CE23A311-551D-42AD-B95D-
          53D60A612551'
     
  • exec sp_executesql N'SELECT
    [Extent1].[YingId] AS [YingId],
    [Extent1].[foo] AS [foo]
    FROM [dbo].[Ying] AS [Extent1]
    WHERE [Extent1].[YingId] = @EntityKeyValue1',N'@EntityKeyValue1
          uniqueidentifier',@EntityKeyValue1='276D0065-9680-4E3F-84EF-
          1EFACEF07ED9'

 
 

One of the extra queries is seen here in SQL Server Profiler:

 
 

Boo! Well, can we get just rid of the join?

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using OldSchool.Models;
namespace OldSchool.Controllers
{
   public class HomeController : Controller
   {
      public ActionResult Index()
      {
         using (RepoEntities myStuff = new RepoEntities())
         {
            List<Dto> myGunk = (from a in myStuff.Yangs select new Dto()
               {
                  Foo = a.Ying.foo,
                  Bar = a.bar,
                  Baz = a.baz,
                  Qux = a.qux
               }).ToList();
            return View(myGunk);
         }
      }
   }
}

 
 

Yes, we are back to the query we had to begin with with no performance loss! Win!

SELECT
1 AS [C1],
[Extent2].[foo] AS [foo],
[Extent1].[bar] AS [bar],
[Extent1].[baz] AS [baz],
[Extent1].[qux] AS [qux]
FROM [dbo].[Yang] AS [Extent1]
INNER JOIN [dbo].[Ying] AS [Extent2] ON [Extent1].[YingId] = [Extent2].[YingId]

 
 

What if we both take out the join and the casting to our object from the call to Entity Framework.

using OldSchool.Models;
namespace OldSchool.Controllers
{
   public class HomeController : Controller
   {
      public ActionResult Index()
      {
         using (RepoEntities myStuff = new RepoEntities())
         {
            List<Dto> myGunk = new List<Dto>();
            foreach (Yang a in myStuff.Yangs)
            {
               myGunk.Add(new Dto()
                  {
                     Foo = a.Ying.foo,
                     Bar = a.bar,
                     Baz = a.baz,
                     Qux = a.qux
                  });
            }
            return View(myGunk);
         }
      }
   }
}

 
 

This takes us back to multiple queries be generated. I won't show you. Use your imagination.

iOS6 has been released in BETA.

You may download it and play with it and face problems like this before telling Apple what you think. This is a new thing for the post-Jobs/otherwise-closed-off Apple. It makes me wonder how much Beta-crazy a company like my own will have to support.

Get SQL Server Authentication working at a new setup of MSSQL Server.

Go to properties for a database, then to Security, and click the radio button for "SQL Server and Windows Authentication mode" to escape errors such as: A connection was successfully established with the server, but then an error occurred during the login process. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.) (Microsoft SQL Server, Error: 233)

Also be sure to do this:

Enable TCP/IP and Named Pipes for various services running MSSQL stuff. You will need to restart the services on the other side of everything I mention above. You may type "Component Services" at the start menu in Windows 7 to get at the services, or if you are lazy like me you can just restart your laptop instead. (How often do you really need to do this bit of prep work. You might as well just restart every time. It won't be often.)

use an Entity Framework .edmx

Here is how to make and use an .edmx assuming you have a database like this. To start with why don't we make an MVC 4 Web API Web Application? Next, let's add a new ADO.NET Entity Data Model called (MyModel.edmx) to the Models folder like so:

We will see a dialog box like so. Let's push forward with the "Generate from database" option.

We will get a dialog box like this next:

It won't be prepped as shown above however. (Note that "RepoEntities" will end up as the name of our data context based on the "Repo" database.) We have to prep it ourselves by clicking on "New Connection..." which will bring up yet another dialog box which looks like this where we have to fill in how to have at our database:

In the last bit of the Entity Data Model Wizard you will check checkboxes for whether or not you want to suck tables, views, stored procedures, or some mixture of the three into the .edmx. The Web.config file will be doctored up to include a connection string on the other side of the wizard. Our .edmx:

I right-clicked in the middle of the .edmx and picked "Add Code Generation Item..." from the menu which popped up. This took me to different dialog box where I had the option to generation an "EF 5.x DbContext Generator" called "Model1.tt" which I did add. I then saved my .edmx. I have a few more files now. If ever some of these files get messed up one may right click on "Model1.tt" and pick "Run Custom Tool" to remake them. Moving forward, I put the following silly code in the HomeController just to test:

using System;
using System.Web.Mvc;
using OldSchool.Models;
namespace OldSchool.Controllers
{
   public class HomeController : Controller
   {
      public ActionResult Index()
      {
         using (RepoEntities myStuff = new RepoEntities())
         {
            Guid myGuid = Guid.NewGuid();
            foreach (Yang yang in myStuff.Yangs)
            {
               string aloha = "hi/bye";
            }
         }
         return View();
      }
   }
}

To keep Yangs from being an ambiguous reference which was confused as to whether the compiler was to read from my new .tt file and/or something that was there before it, I had to destroy some of the old files in the Models folder at the Solution Explorer as seen on the other side of my clean up immediately ABOVE. I was able to run the app, hit a break point and inspect Yangs as seen BELOW. Also on the other side of the hitting the breakpoint a few times, the application does bring up the home page without error. I get this when I move my mouse over "yang" upon first hitting a breakpoint:

Addendum 7/13/2013: Try to ignore Guid myGuid = Guid.NewGuid(); in the code here. It is accidental.

How do I get Chrome to run back on the desktop again in Windows 8 instead of as an app?

Great question! This suggests it is something you toggle on and off at the three hotdogs settings menu. "Relaunch Chrome in Windows 8 mode" and "Relaunch Chrome on the desktop" are the two possible settings.

Friday, July 12, 2013

prepping a database for an Entity Framework .edmx

I am going to give another blog posting after this one on the old school .edmx approach to Entity Framework which, in contrast to the slick, new code first stuff, tightly binds all data back to a marginally more spiffy version of LINQ to SQL or something very much like it. I am helping a friend (Bhavani Akole) with code and in doing so I caught dinner with another friend (Femi Oyekan) tonight who showed me a thing or two about old school EF. Before I can show you any of that, I need to show you how a dummy database I set up is set up. First, I made a database called "Repo" and I put two tables in it. The first table is called "Ying." (Please forgive all the bad names which are to follow.)

Ying is seen above. I made YingId the primary key by making it a uniqueidentifer type, clicking that little key icon to put the key icon at the row for YingId, and also setting the default value to newid() so that when I manually populate rows that I might not have to manually add at Guid into the YingId column. (Instead when I leave the row a Guid will be placed in the cell for me, though my UI for MSSQL Server Management Studio Express 2012 was sluggish to show it.) I then made a Yang table and gave it some columns. I set a YangId as a comparable primary key. It also made another uniqueidentifier type column called YingId. After I had saved off the table, I revisited it in "Design" and right clicked to pick "Relationships..." so that I might tie YingId in Yang to YingId in Ying!

I got a dialog box which looked like this, where I clicked "Add" and then I clicked the button with the three dots by "Tables And Columns Spec."

I then got a second dialog box where I made the association from one YingId to another like so:

I then put some corny data in my two corny tables!

Again, thanks to Olufemi Oyekan for his help tonight.

I promise there is a follow up blog posting coming after this one.

Sogeti

...is no longer my employer. I finished a four month contract for them (with Dell) just over three months ago. They gave me an opportunity the day after it ended to interview for another contract but I botched the interview. Eventually, they got back to me about a second would-be second opportunity, but by that time I had found the full time gig I have now. The best thing about the contract is that I got to do business travel for the first time and go to Nashua, New Hampshire. Word! The photo here is from arriving the first day of the Dell contract (11/27/2012) with two of Sogeti's finest, Josh Louden (left) and Tom Garrett (right).

Thanks to Tom and Josh for a great experience. Also thanks to Matt Hinze for thinking of me for Sogeti.

x86

...implies that the item will be compatible with both 32 bit and 64 bit code. 32 + 64 = 86, get it?

Addendum 9/26/2013: It has been pointed out to me that 32 + 64 = 96 (duh) and that 86 as a name comes from 8086 CPU.

Addendum 3/25/2017: Chris Elgin pointed out this stupid mistake to me. What a guy!

continue; ...in C#

This suggests: "The continue statement passes control to the next iteration of the enclosing iteration statement in which it appears." ...meaning that you may use it in the midst of a loop to go back to the top of the loop running with the next available item to iterate through as the immediate context.

Change the platform target for a Visual Studio project.

Under the properties for a project in Visual Studio, at the Build tab, there is an option for Platform target which is likely set to "Any CPU." You may need to change this to x86. If you do, change the Configuration tab to be sure you are doing it at both Release and Debug modes.

When a missing ClickOnce certificate keeps a WinForms application from running...

In a WinForms app, I unchecked a checkbox for creating a signing certificate for "Sign the ClickOnce manifests" at the "Signing" tab under the User Interface project's properties, and this will hopefully best an error another is seeing asserting:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(2455,5): error MSB3323: Unable to find manifest signing certificate in the certificate store.

 
 

...when he tries to pull my code out of Mecurial. This gave me the idea. I suppose I did not see the error on my end as I made the certificate that was missing. :P

Thursday, July 11, 2013

LINQPad!

http://www.linqpad.net/ has it. I wonder if it helps optimize queries. Anyone know?

Include Actual Execution Plan

I found this which suggests I should use "Include Actual Execution Plan" (a different, comparable icon/feature) in lieu of "Display Estimated Execution Plan" but the former seems to do a lot of nothing. Perhaps this is a problem in using SQL Server Express and perhaps once I get a database onto SQL Server I will be able to use this tool. I'll let you know. :)

Open a SQL Server Compact database in SSMS...

...by picking "Connect Object Explorer..." from the File menu and then setting the "Server type:" option to "SQL Server Compact" in the dialog box which appears. Put the route to the file in the "Database file:" option's field.

Addendum 7/12/2013 Note that per a comment left at this blog posting this "Does not work in SSMS 2012, only 2008/2005."

Try connecting to COMPUTERNAME instead of COMPUTERNAME/MSSSQLSERVER

Good advice from here.

Why can't I select "Management Tools - Complete" in my install of SQL Server?

There should be an option for "Database Engine Tuning Advisor" in the Tools menu in SSMS (MSSQL Server Management Studio) and if there is not, you will need to install "Management Tools - Complete" from your "SQL Server 2008" DVD. You may not have been able to install this in the first pass because, if you experience what I experienced, it was grey-out and only became available after I first installed everything I could and then ran a second install. Also note: In the second pass, the wizard sat at length at a progress bar which said "Gathering user settings." but which did not increment. I eventually gave up and just clicked "Install" to move forward.

Display Estimated Execution Plan

...is an icon one may click in MSSQL Server Management Studio after having run a query to see some graphical analysis of a flow for the query which will show offs where the chokepoints in terms of percentages of time spent for the query are. Hopefully this helps you optimize a query. I don't really understand it yet. Percentages may vary from environment to enviroment and the flow itself may look wildly different run against SQL Server Compact Edition in lieu of SQL Server. I am still trying to understand it.

An .sdf file is a SQL Server Compact Edition Database File.

.mdf is to SQL Server what .sdf is to SQL Server Compact Edition Database File.

There is a bug in iOS6 which sabotages scaling images within HTML5 canvas.

This needs love in iOS6. Images flip and rotate and do inappropriate things. I've seen it!

MyMobiler

Let's say you are using a handheld device such as this Psion WA9212-G1...

...and you cradle it and plug the cradle into your laptop via USB to interface with it. You don't have to interface with the device through its display. Using MyMobiler is a way to get the screen at your laptop so that you may just click about with your mouse.

Wednesday, July 10, 2013

Warm and Cold Reboots

On a Psion WA9212-G1 there is a concept of a Clean Reset which is sort of an in-between for a Warm Reboot and a Cold Reboot. Typically the Cold Reboot is more extreme than a Warm Reboot. The cold will drop the operating system and the warm is akin to just restarting a laptop.

Tuesday, July 9, 2013

a cleaner version of my last blog posting

Considering this:

using System.Collections.Generic;
namespace MyApplication
{
   public static class YieldExample
   {
      public static IEnumerable<decimal> Go()
      {
         decimal[] distances = new decimal[] { 67.8M, 0.7M, 6.001M, 63.3M };
         foreach (decimal distance in distances)
         {
            yield return distance;
         }
      }
   }
}

 
 

Test like so:

using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MyApplication.Tests
{
   [TestClass]
   public class YieldExampleTest
   {
      [TestMethod]
      public void TestMethod()
      {
         IEnumerable<decimal> decimals = YieldExample.Go();
         List<decimal> list = decimals.ToList();
         Assert.AreEqual(list[0], 67.8M);
         Assert.AreEqual(list[1], 0.7M);
         Assert.AreEqual(list[2], 6.001M);
         Assert.AreEqual(list[3], 63.3M);
      }
   }
}

yield return C# example

using System.Collections.Generic;
namespace MyApplication
{
   public static class YieldExample
   {
      public static IEnumerator<decimal> Go()
      {
         decimal[] distances = new decimal[] { 67.8M, 0.7M, 6.001M, 63.3M };
         foreach (decimal distance in distances)
         {
            yield return distance;
         }
      }
   }
}

 
 

Test like so:

using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace MyApplication.Tests
{
   [TestClass]
   public class YieldExampleTest
   {
      [TestMethod]
      public void TestMethod()
      {
         IEnumerator<decimal> decimals = YieldExample.Go();
         decimals.MoveNext();
         Assert.AreEqual(decimals.Current, 67.8M);
         decimals.MoveNext();
         Assert.AreEqual(decimals.Current, 0.7M);
         decimals.MoveNext();
         Assert.AreEqual(decimals.Current, 6.001M);
         decimals.MoveNext();
         Assert.AreEqual(decimals.Current, 63.3M);
      }
   }
}

split inheritance in C#

One may make a class inheirt from both a base class and an interface in C#. This has the following example:

class USBDevice : GenericDevice, IOurDevice

 
 

What is more, the write up suggests that a method on the parent class may satisfy the need of a signature within the interface!

Oak!

I saw Amir Rajan speak on an open source alteration to ASP.NET MVC, which heavily used the dynamic keyword of C#, called Oak last night at the Austin .NET User Group. Oak has an object called Gemini which inheirts from DynamicObject and extends using it in many ways you probably don't want to reevent yourself every time you roll a new project. Fun stuff.

ABS() in SQL returns the absolute value of the number it wraps.

DECLARE @i int;
SET @i = -2147483648;
SELECT ABS(@i);
GO

...is given as an example here where I assume 2147483648 would be returned.

Monday, July 8, 2013

Resize images with HTML5 Canvas.

If someone uploads an image that is too big (in terms of pixel width and pixel height) for an application, the image may be resized in HTML5 Canvas as suggested here. I do not know if there is also a way to save out a sized down version of an image. Wait! I found this which suggests you may resize an image in a canvas before an upload and then use "dataURItoBlob" to sniff the resized file to a binary blob that may be shoved up in an upload. Something copied from the last link:

function dataURItoBlob(dataURI) {
   var binary = atob(dataURI.split(',')[1]);
   var array = [];
   for(var i = 0; i < binary.length; i++) {
      array.push(binary.charCodeAt(i));
   }
   return new Blob([new Uint8Array(array)], {type: 'image/jpeg'});
}

 
 

I have not tried any of this stuff myself yet. I just heard of it today and was fascinated.

touch events versus mouse events

In using dojox 1.9 in an iOS environment both a touch event and a mouse event may fire when an element is touched/clicked causing a behavioral quirk that is not idempotent. This and this touch on the difference between the two sets of events. Perhaps it is best to register either touch events or mouse events in the name of a wonk free user experience.

Search against the file tree in Google Chrome Developer Tools.

Ctrl-O will let you search for a file by name while Shift-Ctrl-O will let you search for a function by name.

Sunday, July 7, 2013

bitcoin

...is a digital currency. Bitcoins are blobs of encrypted gunk. A variety of common open source application is used by parties trading them and verifying them. You need a bitcoin client to do the bitcoin thing. Wikipedia says "a bitcoin address is a cryptographic public key" and I take it they are all unique and unforgeable.

an old school foreach may be the most readable sometimes in my opinion

Using ReSharper on the Get method here, I was able to condense everything but the first two lines (unaltered) and last line (also unaltered) into one line of code. However, I don't know that it is terribly easy to understand, you know?

foreach (string scrapping in from scrapping in scrappings where scrapping.IndexOf(".") > -1 let subscrappings = scrapping.Split(".".ToCharArray()) where subscrappings.Length == 4 && ip == null select scrapping) ip = scrapping.Split("<".ToCharArray())[0].ToLower().Where(character => IsCharacterOfIp(character)).Aggregate(ip, (current, character) => current + character);

Sabrina the Fifth!

I will piggyback onto...
  1. this,
  2. this,
  3. this,
  4. and this
  5. by letting you know that I figured out how to "find myself" within a WinForms app:

using System.IO;
using System.Windows.Forms;
namespace WindowsFormsApplication
{
   public partial class Form1 : Form
   {
      public Form1()
      {
         InitializeComponent();
         label1.Text = Directory.GetCurrentDirectory();
      }
   }
}

 
 

When I ran the app from Visual Studio label1 ended up with this in it:

C:\Apps\WinFormsApp\WindowsFormsApplication\WindowsFormsApplication\bin\Debug

 
 

When I published the app and then ran it label1 ended up with this in it:

C:\Users\Thomas\AppData\Local\Apps\2.0\NZX70T3A.BEY\WN7LA04B.TR4\wind..tion_c42fbaf68a73d8f4_0001.0000_4abed88245962350

While I am doing "Where Am I?" stuff, I wrote a scrapper for http://www.ipchicken.com/ which has not changed significantly since Dustin Wells first showed it to me in 2005. If you call the one public method, you will get back your IP in a string. The code in black exists only to accomodate IPv6 IP addresses. I do not have one myself so I could not test the IPv6 stuff. I also do not know if ipchicken will handle IPv6s correctly either.

using System.IO;
using System.Net;
using System.Text;
namespace WhereAmI.Models
{
   public static class PublicIp
   {
      public static string Get()
      {
         string[] scrappings = ScrapeService().Split(">".ToCharArray());
         string ip = null;
         foreach (string scrapping in scrappings)
         {
            if (scrapping.IndexOf(".") > -1)
            {
               string[] subscrappings = scrapping.Split(".".ToCharArray());
               if (subscrappings.Length == 4 && ip == null)
               {
                  foreach (char character in scrapping
.Split("<".ToCharArray())[0].ToLower())
                  {
                     if (IsCharacterOfIp(character))
                     {
                        ip = ip + character;
                     }
                  }
               }
            }
         }
         return ip;
      }
      
      private static string ScrapeService()
      {
         string url = "http://www.ipchicken.com/";
         HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
         StringBuilder scrappingSpool = new StringBuilder();
         using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
         {
            using (Stream stream = response.GetResponseStream())
            {
               int counter = 0;
               byte[] buffer = new byte[1000000];
               do
               {
                  counter = stream.Read(buffer, 0, buffer.Length);
                  if (counter != 0)
                  {
                     string chunk = Encoding.ASCII.GetString(buffer, 0, counter);
                     scrappingSpool.Append(chunk);
                  }
               } while (counter > 0);
            }
         }
         return scrappingSpool.ToString();
      }
      
      private static bool IsCharacterOfIp(char character)
      {
         if (character == '0') return true;
         if (character == '1') return true;
         if (character == '2') return true;
         if (character == '3') return true;
         if (character == '4') return true;
         if (character == '5') return true;
         if (character == '6') return true;
         if (character == '7') return true;
         if (character == '8') return true;
         if (character == '9') return true;
         
if (character == 'a') return true;
         if (character == 'b') return true;
         if (character == 'c') return true;
         if (character == 'd') return true;
         if (character == 'e') return true;
         if (character == 'f') return true;
         if (character == ':') return true;
         if (character == '%') return true;

         if (character == '.') return true;
         return false;
      }
   }
}

Friday, July 5, 2013

really simple logging

using System.IO;
using Whatever.Core;
namespace Whatever.Infrastructure
{
   public class Logging : ILogging
   {
      public void Write(IClock clock, string message)
      {
         string path = @"C:\log.txt";
         if (!File.Exists(path))
         {
            using (StreamWriter streamWriter = File.CreateText(path))
            {
               streamWriter.WriteLine("beginning log at " + clock.CurrentTime());
            }
         }
         using (StreamWriter streamWriter = File.AppendText(path))
         {
            streamWriter.WriteLine("log at " + clock.CurrentTime() + ": " + message);
         }
      }
   }
}

In Visual Studio 2012, if Embed Interop Types is set to true for a reference in its properties then Copy Local will be forced set to false.

Oh no! Does this mean the .dll for the dependency won't be deployed? No, this suggests that instead the dependency will just become a part of the .dll for the project utilizing it if Embed Interop Types is set to true.

Publishing a WinForms app is a little screwy.

The wizard:
  1. You are first asked "Where do you want to publish the application?" to which I recommend answering with the route to a shared folder.
  2. You are next asked "How will users install the application?" to which I recommend responding by picking the "From a UNC path or file share" option and then reentering the route to the shared folder.
  3. The last question is: "Will the application be available offline?" to which you should answer as you feel fit.
You should end up with a setup.exe which when first clicked will run a ClickOnce installer and in subsequent launches will launch the WinForms application itself! For me, a start menu shortcut was most recently placed at: C:\Users\tjaeschke\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Microsoft\ upon running a setup.exe. A lot of my dependencies seemed to end up at: C:\Users\tjaeschke\AppData\Local\Apps\2.0\T0PXHBYJ.DQY\71D72CJQ.WOB\work..tion_18ad13e67fc8a2c5_0001.0000_2da8119f5228e7d0

 
 

Addendum 8/28/2018: Picking the option for "From a CD-ROM or DVD-ROM" instead in the second step here is really pretty legit. It will allow you to make an installer without a network share. The third step in the wizard will then ask you if the app needs updates and you can just say no like Nancy Reagan. When I ran the installer it put a start menu shortcut at C:\Users\tjaeschk\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\YourNameHere and the .exe executable file itself (which I had to search for) at C:\Users\tjaeschk\AppData\Local\Apps\2.0\Z3ZPX5O6.YH6\5O3QA0VY.E6A\your..tion_5c47e637ef76de4f_0001.0000_1f3bdb73f5a87c19

native error 0x80004005

This is an OLE DB (Object Linking and Embedding, Database) connection error that comes back from MSSQL. It vaguely means that you cannot connect. The first thing to look at is your connection specs. Beyond that, perhaps the database is "sick."

Wednesday, July 3, 2013

.7z is the file extension for the 7-Zip archiver.

Get 7-Zip here.

run a Grunt script

If you have Grunt installed at node as suggested here, you may run a Grunt script merely by typing the name of the file at a command prompt (in Windows 7) once you've navigated to the folder holding the file. Grunt may turn around and prompt node to procure other dependencies (should it not have them) with code such as:

grunt.loadNpmTasks('grunt-jsduck');

npm install and package.json

If you have node installed then opening the command prompt, navigating to any folder, and then typing...

npm install

 
 

...will prompt node to try to find a file in the folder called "package.json" of which the contents might look like so:

{
   "name": "Whatever",
   "version": "0.1.0",
   "devDependencies": {
      "grunt": "~0.4.1",
      "grunt-contrib-jshint": "~0.1.1",
      "grunt-contrib-nodeunit": "~0.1.2",
      "grunt-contrib-copy": "~0.4.1",
      "grunt-contrib-clean": "~0.4.1",
      "grunt-mocha": "~0.3.4",
      "grunt-cli": "~0.1.9",
      "grunt-jsduck": "~0.1.4"
   }
}

 
 

Node will use devDependencies as a list of packages to have. If any of the packages are not yet installed, it will install those packages.