diff --git a/TimberWinR.ExtractID/Program.cs b/TimberWinR.ExtractID/Program.cs
new file mode 100644
index 0000000..ab3ebfc
--- /dev/null
+++ b/TimberWinR.ExtractID/Program.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Microsoft.Win32.SafeHandles;
+using System.Runtime.InteropServices;
+
+namespace TimberWinR.ExtractID
+{
+ class MsiHandle : SafeHandleMinusOneIsInvalid
+ {
+ public MsiHandle()
+ : base(true)
+ { }
+
+ protected override bool ReleaseHandle()
+ {
+ return NativeMethods.MsiCloseHandle(handle) == 0;
+ }
+ }
+
+ class NativeMethods
+ {
+ const string MsiDll = "Msi.dll";
+
+ [DllImport(MsiDll, CharSet = CharSet.Unicode, ExactSpelling = true)]
+ public extern static uint MsiOpenPackageW(string szPackagePath, out MsiHandle product);
+
+ [DllImport(MsiDll, ExactSpelling = true)]
+ public extern static uint MsiCloseHandle(IntPtr hAny);
+
+ [DllImport(MsiDll, CharSet = CharSet.Unicode, ExactSpelling = true)]
+ static extern uint MsiGetProductPropertyW(MsiHandle hProduct, string szProperty, StringBuilder value, ref int length);
+
+
+ [DllImport(MsiDll, ExactSpelling = true)]
+ public static extern int MsiSetInternalUI(int value, IntPtr hwnd);
+
+ public static uint MsiGetProductProperty(MsiHandle hProduct, string szProperty, out string value)
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ int length = sb.Capacity;
+ uint err;
+ value = null;
+ if (0 == (err = MsiGetProductPropertyW(hProduct, szProperty, sb, ref length)))
+ {
+ sb.Length = length;
+ value = sb.ToString();
+ return 0;
+ }
+
+ return err;
+ }
+ }
+
+
+
+ class Program
+ {
+ [STAThread]
+ static int Main(string[] args)
+ {
+ if (args.Length < 2)
+ {
+ Console.Error.WriteLine("Expecting MSI and Tempolate file arguments");
+ return 1;
+ }
+
+ string msiDirectory = args[0];
+ string updateFile = args[1];
+ string newFile = args[2];
+
+ string msiFile = Directory.GetFiles(msiDirectory, "TimberWinR*.msi").FirstOrDefault();
+
+ NativeMethods.MsiSetInternalUI(2, IntPtr.Zero); // Hide all UI. Without this you get a MSI dialog
+
+ MsiHandle msi;
+ uint err;
+ if (0 != (err = NativeMethods.MsiOpenPackageW(msiFile, out msi)))
+ {
+ Console.Error.WriteLine("Can't open MSI, error {0}", err);
+ return 1;
+ }
+
+ // Strings available in all MSIs
+ string productCode;
+ using (msi)
+ {
+ if (0 != NativeMethods.MsiGetProductProperty(msi, "ProductCode", out productCode))
+ throw new InvalidOperationException("Can't obtain product code");
+
+ string contents = File.ReadAllText(args[1]);
+
+ contents = contents.Replace("${PROJECTGUID}", productCode);
+
+ File.WriteAllText(args[2], contents);
+
+ Console.WriteLine("Updated {0} ProductID: {1}", args[2], productCode);
+
+ return 0;
+ }
+
+ Console.Error.WriteLine("Failed for some reason");
+ }
+ }
+}
diff --git a/TimberWinR.ExtractID/Properties/AssemblyInfo.cs b/TimberWinR.ExtractID/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b1f4977
--- /dev/null
+++ b/TimberWinR.ExtractID/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TimberWinR.ExtractID")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TimberWinR.ExtractID")]
+[assembly: AssemblyCopyright("Copyright © 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("cfb670ee-743d-49c7-b2bf-456bac3a88ef")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TimberWinR.ExtractID/TimberWinR.ExtractID.csproj b/TimberWinR.ExtractID/TimberWinR.ExtractID.csproj
new file mode 100644
index 0000000..d13e8fd
--- /dev/null
+++ b/TimberWinR.ExtractID/TimberWinR.ExtractID.csproj
@@ -0,0 +1,55 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {99096939-E9DD-4499-883D-4726745A5843}
+ Exe
+ Properties
+ TimberWinR.ExtractID
+ TimberWinR.ExtractID
+ v4.0
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TimberWinR.ServiceHost/Properties/AssemblyInfo.cs b/TimberWinR.ServiceHost/Properties/AssemblyInfo.cs
index 4333ec8..669faa6 100644
--- a/TimberWinR.ServiceHost/Properties/AssemblyInfo.cs
+++ b/TimberWinR.ServiceHost/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.3.9.0")]
-[assembly: AssemblyFileVersion("1.3.9.0")]
+[assembly: AssemblyVersion("1.3.10.0")]
+[assembly: AssemblyFileVersion("1.3.10.0")]
diff --git a/TimberWinR.sln b/TimberWinR.sln
index 43b314e..aaf3365 100644
--- a/TimberWinR.sln
+++ b/TimberWinR.sln
@@ -26,6 +26,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProjectSection
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "TimberWinR.Wix", "TimberWix\TimberWinR.Wix.wixproj", "{82A39B31-61EC-468D-AA71-0D949AC6528F}"
+ ProjectSection(ProjectDependencies) = postProject
+ {99096939-E9DD-4499-883D-4726745A5843} = {99096939-E9DD-4499-883D-4726745A5843}
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimberWinR.ExtractID", "TimberWinR.ExtractID\TimberWinR.ExtractID.csproj", "{99096939-E9DD-4499-883D-4726745A5843}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -79,6 +84,16 @@ Global
{82A39B31-61EC-468D-AA71-0D949AC6528F}.Release|Mixed Platforms.Build.0 = Release|x86
{82A39B31-61EC-468D-AA71-0D949AC6528F}.Release|x86.ActiveCfg = Release|x86
{82A39B31-61EC-468D-AA71-0D949AC6528F}.Release|x86.Build.0 = Release|x86
+ {99096939-E9DD-4499-883D-4726745A5843}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {99096939-E9DD-4499-883D-4726745A5843}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {99096939-E9DD-4499-883D-4726745A5843}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+ {99096939-E9DD-4499-883D-4726745A5843}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+ {99096939-E9DD-4499-883D-4726745A5843}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {99096939-E9DD-4499-883D-4726745A5843}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {99096939-E9DD-4499-883D-4726745A5843}.Release|Any CPU.Build.0 = Release|Any CPU
+ {99096939-E9DD-4499-883D-4726745A5843}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+ {99096939-E9DD-4499-883D-4726745A5843}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+ {99096939-E9DD-4499-883D-4726745A5843}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/TimberWix/Product.wxs b/TimberWix/Product.wxs
index 2ea72df..c6add2f 100644
--- a/TimberWix/Product.wxs
+++ b/TimberWix/Product.wxs
@@ -6,6 +6,12 @@
c:\logs
Info
5141
+
+
+
+
+
+