2009-07-16 20:54:36 +00:00
#region Disclaimer / License
2010-01-03 22:57:13 +00:00
// Copyright (C) 2010, Kenneth Skovhede
2009-07-16 20:54:36 +00:00
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
using System ;
2009-07-05 11:41:02 +00:00
using System.Collections.Generic ;
using System.Text ;
namespace WixProjBuilder
{
class Program
{
static void Main ( string [] _args )
{
List < string > args = new List < string >( _args );
Dictionary < string , string > options = Duplicati . CommandLine . CommandLineParser . ExtractOptions ( args );
if ( args . Count != 1 )
{
Console . WriteLine ( "Usage: " );
Console . WriteLine ( " WixProjBuilder.exe <projfile> [option=value]" );
return ;
}
if (! System . IO . File . Exists ( args [ 0 ]))
{
Console . WriteLine ( string . Format ( "File not found: {0}" , args [ 0 ]));
return ;
}
string wixpath ;
if ( options . ContainsKey ( "wixpath" ))
wixpath = options [ "wixpath" ];
else
wixpath = System . Environment . GetEnvironmentVariable ( "WIXPATH" );
if ( string . IsNullOrEmpty ( wixpath ))
{
wixpath = System . IO . Path . Combine ( System . IO . Path . Combine ( System . Environment . ExpandEnvironmentVariables ( "%programfiles%" ), "Windows Installer XML v3" ), "bin" );
Console . WriteLine ( string . Format ( "*** wixpath not specified, using: {0}" , wixpath ));
}
args [ 0 ] = System . IO . Path . GetFullPath ( args [ 0 ]);
Console . WriteLine ( string . Format ( "Parsing wixproj file: {0}" , args [ 0 ]));
System . Xml . XmlDocument doc = new System . Xml . XmlDocument ();
doc . Load ( args [ 0 ]);
string config = "Release" ;
if ( options . ContainsKey ( "configuration" ))
config = options [ "configuration" ];
string projdir = System . IO . Path . GetDirectoryName ( System . IO . Path . GetFullPath ( args [ 0 ]));
List < string > includes = new List < string >();
List < string > refs = new List < string >();
List < string > content = new List < string >();
System . Xml . XmlNamespaceManager nm = new System . Xml . XmlNamespaceManager ( doc . NameTable );
nm . AddNamespace ( "ms" , "http://schemas.microsoft.com/developer/msbuild/2003" );
foreach ( System . Xml . XmlNode n in doc . SelectNodes ( "ms:Project/ms:ItemGroup/ms:Compile" , nm ))
includes . Add ( n . Attributes [ "Include" ]. Value );
foreach ( System . Xml . XmlNode n in doc . SelectNodes ( "ms:Project/ms:ItemGroup/ms:Content" , nm ))
content . Add ( n . Attributes [ "Include" ]. Value );
foreach ( System . Xml . XmlNode n in doc . SelectNodes ( "ms:Project/ms:ItemGroup/ms:WixExtension" , nm ))
refs . Add ( n . Attributes [ "Include" ]. Value );
string objdir = System . IO . Path . Combine ( System . IO . Path . Combine ( projdir , "obj" ), config );
string packagename = "output" ;
string outdir = System . IO . Path . Combine ( "bin" , config );
string outtype = "Package" ;
//TODO: Support multiconfiguration system correctly
foreach ( System . Xml . XmlNode n in doc . SelectNodes ( "ms:Project/ms:PropertyGroup/ms:Configuration" , nm ))
if ( true ) //if (string.Compare(n.InnerText, config, true) == 0)
{
System . Xml . XmlNode p = n . ParentNode ;
if ( p [ "OutputName" ] != null )
packagename = p [ "OutputName" ]. InnerText ;
if ( p [ "OutputType" ] != null )
outtype = p [ "OutputType" ]. InnerText ;
if ( p [ "OutputPath" ] != null )
outdir = p [ "OutputPath" ]. InnerText . Replace ( "$(Configuration)" , config );
if ( p [ "IntermediateOutputPath" ] != null )
objdir = p [ "IntermediateOutputPath" ]. InnerText . Replace ( "$(Configuration)" , config );
}
if (! objdir . EndsWith ( System . IO . Path . DirectorySeparatorChar . ToString ()))
objdir += System . IO . Path . DirectorySeparatorChar ;
string msiname = System . IO . Path . Combine ( outdir , packagename + ".msi" );
Console . WriteLine ( " Compiling ... " );
if ( includes . Count == 0 )
{
Console . WriteLine ( "No files found to compile in project file" );
return ;
}
string compile_args = "\"" + string . Join ( "\" \"" , includes . ToArray ()) + "\"" ;
compile_args += " -out \"" + objdir . Replace ( "\\" , "\\\\" ) + "\"" ;
2010-10-27 20:11:42 +00:00
if ( options . ContainsKey ( "platform" ) && options [ "platform" ] == "x64" )
compile_args += " -dPlatform=x64 -dWin64=yes" ;
else
compile_args += " -dPlatform=x86 -dWin64=no" ;
2009-07-05 11:41:02 +00:00
int res = Execute (
System . IO . Path . Combine ( wixpath , "candle.exe" ),
projdir ,
compile_args );
if ( res != 0 )
{
Console . WriteLine ( "Compilation failed, aborting" );
return ;
}
Console . WriteLine ( " Linking ..." );
for ( int i = 0 ; i < includes . Count ; i ++)
includes [ i ] = System . IO . Path . Combine ( objdir , System . IO . Path . GetFileNameWithoutExtension ( includes [ i ]) + ".wixobj" );
for ( int i = 0 ; i < refs . Count ; i ++)
if (! System . IO . Path . IsPathRooted ( refs [ i ]))
{
refs [ i ] = FindDll ( refs [ i ] + ".dll" , new string [] { projdir , wixpath });
if (! System . IO . Path . IsPathRooted ( refs [ i ]))
refs [ i ] = FindDll ( refs [ i ]);
}
string link_args = "\"" + string . Join ( "\" \"" , includes . ToArray ()) + "\"" ;
if ( refs . Count > 0 )
link_args += " -ext \"" + string . Join ( "\" -ext \"" , refs . ToArray ()) + "\"" ;
link_args += " -out \"" + msiname + "\"" ;
res = Execute (
System . IO . Path . Combine ( wixpath , "light.exe" ),
projdir ,
link_args );
if ( res != 0 )
{
Console . WriteLine ( "Link failed, aborting" );
return ;
}
if (! System . IO . Path . IsPathRooted ( msiname ))
msiname = System . IO . Path . GetFullPath ( System . IO . Path . Combine ( projdir , msiname ));
Console . WriteLine ( string . Format ( "Done: {0}" , msiname ));
}
private static int Execute ( string app , string workdir , string args )
{
System . Diagnostics . ProcessStartInfo psi = new System . Diagnostics . ProcessStartInfo ( app , args );
psi . CreateNoWindow = true ;
psi . WindowStyle = System . Diagnostics . ProcessWindowStyle . Hidden ;
psi . WorkingDirectory = workdir ;
psi . RedirectStandardOutput = true ;
psi . RedirectStandardError = true ;
psi . UseShellExecute = false ;
System . Diagnostics . Process p = System . Diagnostics . Process . Start ( psi );
2009-07-16 20:54:36 +00:00
p . WaitForExit ( 5 * 60 * 1000 ); //Wait up to five minutes
2009-07-05 11:41:02 +00:00
if (! p . HasExited )
{
try { p . Kill (); }
catch { }
Console . WriteLine ( "Stdout: " + p . StandardOutput . ReadToEnd ());
Console . WriteLine ( "Stderr: " + p . StandardError . ReadToEnd ());
throw new Exception ( string . Format ( "Application {0} hung" , app ));
}
Console . WriteLine ();
Console . WriteLine ( p . StandardOutput . ReadToEnd ());
Console . WriteLine ( p . StandardError . ReadToEnd ());
Console . WriteLine ();
return p . ExitCode ;
}
private static string FindDll ( string filename )
{
return FindDll ( filename , System . Environment . GetEnvironmentVariable ( "path" ). Split ( System . IO . Path . PathSeparator ));
}
private static string FindDll ( string filename , IEnumerable < string > paths )
{
foreach ( string p in paths )
if ( System . IO . File . Exists ( System . IO . Path . Combine ( p , filename )))
return System . IO . Path . Combine ( p , filename );
return filename ;
}
}
}