diff --git a/share/qtcreator/templates/wizards/scriptgeneratedproject/generate.pl b/share/qtcreator/templates/wizards/scriptgeneratedproject/generate.pl
index 3f4103c18139e929ef379c38ad4e499c7d882512..580991ea057ba44dd9e979155111419b930dfa41 100755
--- a/share/qtcreator/templates/wizards/scriptgeneratedproject/generate.pl
+++ b/share/qtcreator/templates/wizards/scriptgeneratedproject/generate.pl
@@ -34,45 +34,59 @@ use Getopt::Long;
 use IO::File;
 
 my $optDryRun = 0;
-my $fieldClassName = 'MyClass';
-my $standardFieldProjectName = 'MyProject';
-my $standardFieldCppHeaderSuffix = 'h';
-my $standardFieldCppSourceSuffix = 'cpp';
+my $optHelp = 0;
+my $optClassName = 'MyClass';
+my $optProjectName = 'MyProject';
+my $optCppHeaderSuffix = 'h';
+my $optCppSourceSuffix = 'cpp';
+my $optDescription = '';
+
+# -- Read in a file and return its lines
+sub readFile
+{
+    my ($fileName) = @_;
+    my @rc = ();
+    my $fh = new IO::File('<' . $fileName) or die ('Unable to open for reading ' .  $fileName . ' :' . $!);
+    while (my $line = <$fh>) {
+	chomp($line);
+        push (@rc, $line);
+    }
+    $fh->close();
+    return @rc;
+}
 
 my $USAGE=<<EOF;
-Usage: generate.pl [--dry-run] <parameter-mappings>
+Usage: generate.pl [--help] | [--dry-run]
+                   [--class-name=<class name>]
+                   [--project-name=<project name>]
+                   [--header-suffix=<header suffix>]
+                   [--source-suffix=<source suffix>]
+                   [--description=<description-file>]
 
 Custom wizard project generation example script.
 
-Known parameters: ClassName=<value>
 EOF
 
-if (!GetOptions("dry-run" => \$optDryRun)) {
-    print $USAGE;
-    exit (1);
-}
-
-if (scalar(@ARGV) == 0) {
+my $argCount = scalar(@ARGV);
+if ($argCount == 0
+    || !GetOptions("help" => \$optHelp,
+                   "dry-run" => \$optDryRun,
+                   "class-name:s" => \$optClassName,
+                   "project-name:s" => \$optProjectName,
+                   "header-suffix:s" => \$optCppHeaderSuffix,
+                   "source-suffix:s" => \$optCppSourceSuffix,
+                   "description:s" => \$optDescription)
+    || $optHelp != 0) {
     print $USAGE;
     exit (1);
 }
 
-# -- Parse the 'field=value' pairs
-foreach my $arg (@ARGV) {
-    my ($key, $value) = split('=', $arg);
-    $fieldClassName = $value if ($key eq 'ClassName');
-#   -- Standard fields defined by the custom project wizard
-    $standardFieldProjectName = $value if ($key eq 'ProjectName');
-    $standardFieldCppHeaderSuffix = $value if ($key eq 'CppHeaderSuffix');
-    $standardFieldCppSourceSuffix = $value if ($key eq 'CppSourceSuffix');
-}
-
 # -- Determine file names
-my $baseFileName = lc($fieldClassName);
-my $sourceFileName = $baseFileName . '.' . $standardFieldCppSourceSuffix;
-my $headerFileName = $baseFileName . '.' . $standardFieldCppHeaderSuffix;
-my $mainSourceFileName = 'main.' . $standardFieldCppSourceSuffix;
-my $projectFileName = lc($standardFieldProjectName) . '.pro';
+my $baseFileName = lc($optClassName);
+my $sourceFileName = $baseFileName . '.' . $optCppSourceSuffix;
+my $headerFileName = $baseFileName . '.' . $optCppHeaderSuffix;
+my $mainSourceFileName = 'main.' . $optCppSourceSuffix;
+my $projectFileName = lc($optProjectName) . '.pro';
 
 if ($optDryRun) {
 #   -- Step 1) Dry run: Print file names along with attributes
@@ -85,23 +99,29 @@ if ($optDryRun) {
     print 'Generating ',  $headerFileName, ' ', $sourceFileName, ' ',
           $mainSourceFileName, ' ', $projectFileName, "\n";
     my $headerFile = new IO::File('>' . $headerFileName) or die ('Unable to open ' . $headerFileName . ' :' . $!);
-    print $headerFile '#ifndef ', uc($fieldClassName), "_H\n#define ", uc($fieldClassName), "_H\n\n",
-          'class ', $fieldClassName, "{\npublic:\n    ", $fieldClassName, "();\n\n};\n\n#endif\n";
+    print $headerFile '#ifndef ', uc($optClassName), "_H\n#define ", uc($optClassName), "_H\n\n",
+          'class ', $optClassName, "{\npublic:\n    ", $optClassName, "();\n\n};\n\n#endif\n";
     $headerFile->close();
 
     my $sourceFile = new IO::File('>' . $sourceFileName) or die ('Unable to open ' . $sourceFileName . ' :' . $!);
     print $sourceFile  '#include "', $headerFileName ,"\"\n\n",
-            $fieldClassName,'::', $fieldClassName, "()\n{\n}\n";
+            $optClassName,'::', $optClassName, "()\n{\n}\n";
     $sourceFile->close();
 
     my $mainSourceFile = new IO::File('>' . $mainSourceFileName) or die ('Unable to open ' . $mainSourceFileName . ' :' . $!);
-    print $mainSourceFile  '#include "', $headerFileName ,"\"\n\n",
-          "int main(int argc, char *argv[])\n{\n    ", $fieldClassName,' ', lc($fieldClassName),
+    print $mainSourceFile  '#include "', $headerFileName ,"\"\n\n";
+#   -- Write out description comments
+    if ($optDescription ne '') {
+        foreach my $description (readFile($optDescription)) {
+	    print $mainSourceFile  '// ', $description, "\n";
+	}
+    }
+    print $mainSourceFile "int main(int argc, char *argv[])\n{\n    ", $optClassName,' ', lc($optClassName),
           ";\n    return 0;\n}\n";
     $mainSourceFile->close();
 
     my $projectFile = new IO::File('>' . $projectFileName) or die ('Unable to open ' . $projectFileName . ' :' . $!);
-    print $projectFile "TEMPLATE = app\nQT -= core\nCONFIG += console\nTARGET = ", $standardFieldProjectName,
+    print $projectFile "TEMPLATE = app\nQT -= core\nCONFIG += console\nTARGET = ", $optProjectName,
           "\nSOURCES += ", $sourceFileName, ' ',$headerFileName, ' ', $mainSourceFileName,
           "\nHEADERS += ", $headerFileName,"\n";
     $projectFile->close();
diff --git a/share/qtcreator/templates/wizards/scriptgeneratedproject/wizard_sample.xml b/share/qtcreator/templates/wizards/scriptgeneratedproject/wizard_sample.xml
index 09d55cd24ee3f272c894e5a31be65730ec917298..35e31897f0d219a0ac928cbf75409c3bd3be6f48 100644
--- a/share/qtcreator/templates/wizards/scriptgeneratedproject/wizard_sample.xml
+++ b/share/qtcreator/templates/wizards/scriptgeneratedproject/wizard_sample.xml
@@ -34,8 +34,6 @@ Custom class wizard example configuration file. -->
     <description>Creates a simple project using a generator script</description>
     <displayname>Simple Script-Generated Project</displayname>;
     <displaycategory>Custom Projects</displaycategory>
-    <!-- Specify the generator script -->
-    <files generatorscript="generate.pl"/>
     <!-- Create parameter wizard page -->
     <fieldpagetitle>Simple Script-Generated Project Parameters</fieldpagetitle>
     <fields>
@@ -43,5 +41,19 @@ Custom class wizard example configuration file. -->
             <fieldcontrol class="QLineEdit" validator="^[a-zA-Z0-9_]+$" defaulttext="MyClass" />
             <fielddescription>Class name:</fielddescription>
         </field>
+	<!-- Description will be inserted as a multi-line C++-comment -->
+        <field name="Description">
+            <fieldcontrol class="QTextEdit" defaulttext="Enter description" />
+            <fielddescription>Description:</fielddescription>
+        </field>
     </fields>
+    <!-- Specify the generator script -->
+    <generatorscript binary="generate.pl">
+        <argument value="--class-name=%ClassName%"/>
+        <argument value="--project-name=%ProjectName%"/>
+        <argument value="--header-suffix=%CppHeaderSuffix%" omit-empty="true"/>
+        <argument value="--source-suffix=%CppSourceSuffix%" omit-empty="true"/>
+	 <!-- Multi-line description passed as temporary file unless empty -->
+        <argument value="--description=%Description%" omit-empty="true" write-file="true"/>
+    </generatorscript>
 </wizard>
diff --git a/src/plugins/projectexplorer/customwizard/customwizard.cpp b/src/plugins/projectexplorer/customwizard/customwizard.cpp
index 2a84d2ed5721b772671b33e1bd2f70b16b161a4e..7ab2a611be17fb6ecb8a1ea5704ab47414cc25fe 100644
--- a/src/plugins/projectexplorer/customwizard/customwizard.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizard.cpp
@@ -225,7 +225,9 @@ bool CustomWizard::writeFiles(const Core::GeneratedFiles &files, QString *errorM
         }
     }
     // Run the custom script to actually generate the files.
-    if (!Internal::runCustomWizardGeneratorScript(ctx->targetPath, d->m_parameters->filesGeneratorScriptFullPath(),
+    if (!Internal::runCustomWizardGeneratorScript(ctx->targetPath,
+                                                  d->m_parameters->filesGeneratorScript,
+                                                  d->m_parameters->filesGeneratorScriptArguments,
                                                   ctx->replacements, errorMessage))
         return false;
     // Paranoia: Check on the files generated by the script:
@@ -233,7 +235,7 @@ bool CustomWizard::writeFiles(const Core::GeneratedFiles &files, QString *errorM
         if (generatedFile.attributes() & Core::GeneratedFile::CustomGeneratorAttribute)
             if (!QFileInfo(generatedFile.path()).isFile()) {
                 *errorMessage = QString::fromLatin1("%1 failed to generate %2").
-                        arg(d->m_parameters->filesGeneratorScript, generatedFile.path());
+                        arg(d->m_parameters->filesGeneratorScript.back(), generatedFile.path());
                 return false;
             }
     return true;
@@ -253,7 +255,8 @@ Core::GeneratedFiles CustomWizard::generateWizardFiles(QString *errorMessage) co
     // If generator script is non-empty, do a dry run to get it's files.
     if (!d->m_parameters->filesGeneratorScript.isEmpty()) {
         rc += Internal::dryRunCustomWizardGeneratorScript(ctx->targetPath,
-                                                          d->m_parameters->filesGeneratorScriptFullPath(),
+                                                          d->m_parameters->filesGeneratorScript,
+                                                          d->m_parameters->filesGeneratorScriptArguments,
                                                           ctx->replacements, errorMessage);
         if (rc.isEmpty())
             return rc;
diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
index eab3f8616554b49565d0c570f3df6a5fcb3fb5fd..f3d8fe9591f80a79a28a57721a11a2e6aa6bbf53 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.cpp
@@ -29,18 +29,24 @@
 
 #include "customwizardparameters.h"
 #include "customwizardpreprocessor.h"
+#include "customwizardscriptgenerator.h"
 
 #include <coreplugin/mimedatabase.h>
 #include <coreplugin/icore.h>
 #include <cpptools/cpptoolsconstants.h>
 
+#include <utils/qtcassert.h>
+
 #include <QtCore/QDebug>
 #include <QtCore/QCoreApplication>
 #include <QtCore/QLocale>
 #include <QtCore/QFile>
+#include <QtCore/QDir>
 #include <QtCore/QFileInfo>
 #include <QtCore/QXmlStreamReader>
 #include <QtCore/QXmlStreamAttribute>
+#include <QtCore/QTemporaryFile>
+
 #include <QtGui/QIcon>
 
 enum { debug = 0 };
@@ -64,6 +70,13 @@ static const char comboEntriesElementC[] = "comboentries";
 static const char comboEntryElementC[] = "comboentry";
 static const char comboEntryTextElementC[] = "comboentrytext";
 
+static const char generatorScriptElementC[] = "generatorscript";
+static const char generatorScriptBinaryAttributeC[] = "binary";
+static const char generatorScriptArgumentElementC[] = "argument";
+static const char generatorScriptArgumentValueAttributeC[] = "value";
+static const char generatorScriptArgumentOmitEmptyAttributeC[] = "omit-empty";
+static const char generatorScriptArgumentWriteFileAttributeC[] = "write-file";
+
 static const char fieldDescriptionElementC[] = "fielddescription";
 static const char fieldNameAttributeC[] = "name";
 static const char fieldMandatoryAttributeC[] = "mandatory";
@@ -87,6 +100,8 @@ enum ParseState {
     ParseWithinComboEntryText,
     ParseWithinFiles,
     ParseWithinFile,
+    ParseWithinScript,
+    ParseWithinScriptArguments,
     ParseError
 };
 
@@ -136,6 +151,7 @@ void CustomWizardParameters::clear()
     files.clear();
     fields.clear();
     filesGeneratorScript.clear();
+    filesGeneratorScriptArguments.clear();
     firstPageId = -1;
 }
 
@@ -276,6 +292,8 @@ static ParseState nextOpeningState(ParseState in, const QStringRef &name)
             return ParseWithinFields;
         if (name == QLatin1String(filesElementC))
             return ParseWithinFiles;
+        if (name == QLatin1String(generatorScriptElementC))
+            return ParseWithinScript;
         break;
     case ParseWithinFields:
         if (name == QLatin1String(fieldElementC))
@@ -303,10 +321,15 @@ static ParseState nextOpeningState(ParseState in, const QStringRef &name)
         if (name == QLatin1String(fileElementC))
             return ParseWithinFile;
         break;
+    case ParseWithinScript:
+        if (name == QLatin1String(generatorScriptArgumentElementC))
+            return ParseWithinScriptArguments;
+        break;
     case ParseWithinFieldDescription: // No subelements
     case ParseWithinComboEntryText:
     case ParseWithinFile:
     case ParseError:
+    case ParseWithinScriptArguments:
         break;
     }
     return ParseError;
@@ -358,6 +381,14 @@ static ParseState nextClosingState(ParseState in, const QStringRef &name)
         if (name == QLatin1String(comboEntryTextElementC))
             return ParseWithinComboEntry;
         break;
+    case ParseWithinScript:
+        if (name == QLatin1String(generatorScriptElementC))
+            return ParseWithinWizard;
+        break;
+    case ParseWithinScriptArguments:
+        if (name == QLatin1String(generatorScriptArgumentElementC))
+            return ParseWithinScript;
+        break;
     case ParseError:
         break;
     }
@@ -427,6 +458,11 @@ static inline QString localeLanguage()
     return name;
 }
 
+GeneratorScriptArgument::GeneratorScriptArgument(const QString &v) :
+    value(v), flags(0)
+{
+}
+
 // Main parsing routine
 CustomWizardParameters::ParseResult
      CustomWizardParameters::parse(QIODevice &device,
@@ -499,7 +535,6 @@ CustomWizardParameters::ParseResult
                 }
                      break;
                 case ParseWithinFiles:
-                    filesGeneratorScript = attributeValue(reader, filesGeneratorScriptAttributeC);
                     break;
                 case ParseWithinFile: { // file attribute
                         CustomWizardFile file;
@@ -516,6 +551,26 @@ CustomWizardParameters::ParseResult
                         }
                     }
                     break;
+                case ParseWithinScript:
+                    filesGeneratorScript = fixGeneratorScript(configFileFullPath, attributeValue(reader, generatorScriptBinaryAttributeC));
+                    if (filesGeneratorScript.isEmpty()) {
+                        *errorMessage = QString::fromLatin1("No binary specified for generator script.");
+                        return ParseFailed;
+                    }
+                    break;
+                case ParseWithinScriptArguments: {
+                    GeneratorScriptArgument argument(attributeValue(reader, generatorScriptArgumentValueAttributeC));
+                    if (argument.value.isEmpty()) {
+                        *errorMessage = QString::fromLatin1("No value specified for generator script argument.");
+                        return ParseFailed;
+                    }
+                    if (booleanAttributeValue(reader, generatorScriptArgumentOmitEmptyAttributeC, false))
+                        argument.flags |= GeneratorScriptArgument::OmitEmpty;
+                    if (booleanAttributeValue(reader, generatorScriptArgumentWriteFileAttributeC, false))
+                        argument.flags |= GeneratorScriptArgument::WriteFile;
+                    filesGeneratorScriptArguments.push_back(argument);
+                }
+                    break;
                 default:
                     break;
                 }
@@ -559,23 +614,26 @@ CustomWizardParameters::ParseResult
     return parse(configFile, configFileFullPath, bp, errorMessage);
 }
 
-QString CustomWizardParameters::filesGeneratorScriptFullPath() const
-{
-    if (filesGeneratorScript.isEmpty())
-        return QString();
-    QString rc = directory;
-    rc += QLatin1Char('/');
-    rc += filesGeneratorScript;
-    return rc;
-}
-
 QString CustomWizardParameters::toString() const
 {
     QString rc;
     QTextStream str(&rc);
     str << "Directory: " << directory << " Klass: '" << klass << "'\n";
-    if (!filesGeneratorScript.isEmpty())
-        str << "Script: '" <<  filesGeneratorScript << "'\n";
+    if (!filesGeneratorScriptArguments.isEmpty()) {
+        str << "Script:";
+        foreach(const QString &a, filesGeneratorScript)
+            str << " '" << a << '\'';
+        str << "\nArguments: ";
+        foreach(const GeneratorScriptArgument &a, filesGeneratorScriptArguments) {
+            str << " '" << a.value  << '\'';
+            if (a.flags & GeneratorScriptArgument::OmitEmpty)
+                str << " [omit empty]";
+            if (a.flags & GeneratorScriptArgument::WriteFile)
+                str << " [write file]";
+            str << ',';
+        }
+        str << '\n';
+    }
     foreach(const CustomWizardFile &f, files) {
         str << "  File source: " << f.source << " Target: " << f.target;
         if (f.openEditor)
@@ -603,8 +661,16 @@ QString CustomWizardParameters::toString() const
 
 // ------------ CustomWizardContext
 
-void CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *s)
+static inline QString passThrough(const QString &in) { return in; }
+
+// Do field replacements applying modifiers and string transformation
+// for the value
+template <class ValueStringTransformation>
+bool replaceFieldHelper(ValueStringTransformation transform,
+                        const CustomWizardContext::FieldReplacementMap &fm,
+                        QString *s)
 {
+    bool nonEmptyReplacements = false;
     if (debug) {
         qDebug().nospace() << "CustomWizardContext::replaceFields with " <<
                 fm << *s;
@@ -633,7 +699,7 @@ void CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *
             modifier = fieldSpec.at(fieldSpecSize - 1).toLatin1();
             fieldSpec.truncate(fieldSpecSize - 2);
         }
-        const FieldReplacementMap::const_iterator it = fm.constFind(fieldSpec);
+        const CustomWizardContext::FieldReplacementMap::const_iterator it = fm.constFind(fieldSpec);
         if (it == fm.constEnd()) {
             pos = nextPos; // Not found, skip
             continue;
@@ -655,9 +721,64 @@ void CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *
         default:
             break;
         }
-        s->replace(pos, nextPos - pos, replacement);
+        if (!replacement.isEmpty())
+            nonEmptyReplacements = true;
+        // Apply transformation to empty values as well.
+        s->replace(pos, nextPos - pos, transform(replacement));
+        nonEmptyReplacements = true;
         pos += replacement.size();
     }
+    return nonEmptyReplacements;
+}
+
+bool CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *s)
+{
+    return replaceFieldHelper(passThrough, fm, s);
+}
+
+// Transformation to be passed to replaceFieldHelper(). Writes the
+// value to a text file and returns the file name to be inserted
+// instead of the expanded field in the parsed template,
+// used for the arguments of a generator script.
+class TemporaryFileTransform {
+public:
+    typedef CustomWizardContext::TemporaryFilePtr TemporaryFilePtr;
+    typedef CustomWizardContext::TemporaryFilePtrList TemporaryFilePtrList;
+
+    explicit TemporaryFileTransform(TemporaryFilePtrList *f);
+
+    QString operator()(const QString &) const;
+
+private:
+    TemporaryFilePtrList *m_files;
+    QString m_pattern;
+};
+
+TemporaryFileTransform::TemporaryFileTransform(TemporaryFilePtrList *f) :
+    m_files(f), m_pattern(QDir::tempPath())
+{
+    if (!m_pattern.endsWith(QLatin1Char('/')))
+        m_pattern += QLatin1Char('/');
+    m_pattern += QLatin1String("qtcreatorXXXXXX.txt");
+}
+
+QString TemporaryFileTransform::operator()(const QString &value) const
+{
+    TemporaryFilePtr temporaryFile(new QTemporaryFile(m_pattern));
+    QTC_ASSERT(temporaryFile->open(), return QString(); )
+
+    temporaryFile->write(value.toLocal8Bit());
+    const QString name = temporaryFile->fileName();
+    temporaryFile->flush();
+    temporaryFile->close();
+    m_files->push_back(temporaryFile);
+    return name;
+}
+
+bool CustomWizardContext::replaceFields(const FieldReplacementMap &fm, QString *s,
+                                        TemporaryFilePtrList *files)
+{
+    return replaceFieldHelper(TemporaryFileTransform(files), fm, s);
 }
 
 void CustomWizardContext::reset()
diff --git a/src/plugins/projectexplorer/customwizard/customwizardparameters.h b/src/plugins/projectexplorer/customwizard/customwizardparameters.h
index 64f601d5f7145a341dd21537ef65f6d3b83aaaf4..5c757e2b835f31ff458620057677c6d008507c4d 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardparameters.h
+++ b/src/plugins/projectexplorer/customwizard/customwizardparameters.h
@@ -32,12 +32,14 @@
 
 #include <coreplugin/basefilewizard.h>
 
-#include <QtCore/QList>
+#include <QtCore/QStringList>
 #include <QtCore/QMap>
+#include <QtCore/QSharedPointer>
 
 QT_BEGIN_NAMESPACE
 class QIODevice;
 class QDebug;
+class QTemporaryFile;
 QT_END_NAMESPACE
 
 namespace ProjectExplorer {
@@ -68,6 +70,23 @@ struct CustomWizardFile {
     bool openProject;
 };
 
+// Argument to the generator script containing placeholders to
+// be replaced by field values or file names
+// as in '--class-name=%ClassName%' or '--description=%Description%'.
+struct GeneratorScriptArgument {
+    enum Flags {
+        // Omit this arguments if all field placeholders expanded to empty strings.
+        OmitEmpty = 0x1,
+        // Do use the actual field value, but write it to a temporary
+        // text file and inserts its file name (suitable for multiline texts).
+        WriteFile = 0x2 };
+
+    explicit GeneratorScriptArgument(const QString &value = QString());
+
+    QString value;
+    unsigned flags;
+};
+
 struct CustomWizardParameters
 {
 public:
@@ -81,12 +100,12 @@ public:
                       Core::BaseFileWizardParameters *bp, QString *errorMessage);
     QString toString() const;
 
-    QString filesGeneratorScriptFullPath() const;
-
     QString directory;
     QString klass;
     QList<CustomWizardFile> files;
-    QString filesGeneratorScript;
+    QStringList filesGeneratorScript; // Complete binary, such as 'cmd /c myscript.pl'.
+    QList<GeneratorScriptArgument> filesGeneratorScriptArguments;
+
     QString fieldPageTitle;
     QList<CustomWizardField> fields;
     int firstPageId;
@@ -102,14 +121,24 @@ public:
 
 struct CustomWizardContext {
     typedef QMap<QString, QString> FieldReplacementMap;
+    typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr;
+    typedef QList<TemporaryFilePtr> TemporaryFilePtrList;
 
     void reset();
 
     // Replace field values delimited by '%' with special modifiers:
     // %Field% -> simple replacement
     // %Field:l% -> lower case replacement, 'u' upper case,
-    // 'c' capitalize first letter.
-    static void replaceFields(const FieldReplacementMap &fm, QString *s);
+    // 'c' capitalize first letter. Return value indicates whether non-empty
+    // replacements where encountered
+    static bool replaceFields(const FieldReplacementMap &fm, QString *s);
+
+    // Special replaceFields() overload used for the arguments of a generator
+    // script: Write the expanded field values out to temporary files and
+    // inserts file names instead of the expanded fields in string 's'.
+    static bool replaceFields(const FieldReplacementMap &fm, QString *s,
+                              TemporaryFilePtrList *files);
+
     static QString processFile(const FieldReplacementMap &fm, QString in);
 
     FieldReplacementMap baseReplacements;
diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
index 4fb95c5d42b07178f2ece505f3c686b33acdc8d4..5b6c2bef19a92740b90408a3c97abf47d8ae50f4 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
+++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.cpp
@@ -29,7 +29,9 @@
 
 #include "customwizardscriptgenerator.h"
 #include "customwizard.h"
-#include "customwizardparameters.h" // XML attributes
+#include "customwizardparameters.h"
+
+#include <utils/qtcassert.h>
 
 #include <QtCore/QProcess>
 #include <QtCore/QDir>
@@ -41,84 +43,74 @@
 namespace ProjectExplorer {
 namespace Internal {
 
-typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr;
-
-// Format pattern for temporary files
-static inline QString tempFilePattern()
-{
-    QString tempPattern = QDir::tempPath();
-    if (!tempPattern.endsWith(QLatin1Char('/')))
-        tempPattern += QLatin1Char('/');
-    tempPattern += QLatin1String("qtcreatorXXXXXX.txt");
-    return tempPattern;
-}
-
-// Create a temporary file with content
-static inline TemporaryFilePtr writeTemporaryFile(const QString &content)
+// Parse helper: Determine the correct binary to run:
+// Expand to full wizard path if it is relative and located
+// in the wizard directory, else assume it can be found in path.
+// On Windows, run non-exe files with 'cmd /c'.
+QStringList fixGeneratorScript(const QString &configFile, QString binary)
 {
-    TemporaryFilePtr temporaryFile(new QTemporaryFile(tempFilePattern()));
-    if (!temporaryFile->open())
-        return TemporaryFilePtr();
-    temporaryFile->write(content.toLocal8Bit());
-    temporaryFile->close();
-    return temporaryFile;
+    if (binary.isEmpty())
+        return QStringList();
+    // Expand to full path if it is relative and in the wizard
+    // directory, else assume it can be found in path.
+    QFileInfo binaryInfo(binary);
+    if (!binaryInfo.isAbsolute()) {
+        QString fullPath = QFileInfo(configFile).absolutePath();
+        fullPath += QLatin1Char('/');
+        fullPath += binary;
+        const QFileInfo fullPathInfo(fullPath);
+        if (fullPathInfo.isFile()) {
+            binary = fullPathInfo.absoluteFilePath();
+            binaryInfo = fullPathInfo;
+        }
+    } // not absolute
+    QStringList rc(binary);
+#ifdef Q_OS_WIN // Windows: Cannot run scripts by QProcess, do 'cmd /c'
+    const QString extension = binaryInfo.suffix();
+    if (!extension.isEmpty() && extension.compare(QLatin1String("exe"), Qt::CaseInsensitive) != 0) {
+        rc.push_front(QLatin1String("/C"));
+        rc.push_front(QString::fromLocal8Bit(qgetenv("COMSPEC")));
+        if (rc.front().isEmpty())
+            rc.front() = QLatin1String("cmd.exe");
+    }
+#endif
+    return rc;
 }
 
 // Helper for running the optional generation script.
 static bool
     runGenerationScriptHelper(const QString &workingDirectory,
-                              QString binary, bool dryRun,
+                              const QStringList &script,
+                              const QList<GeneratorScriptArgument> &argumentsIn,
+                              bool dryRun,
                               const QMap<QString, QString> &fieldMap,
                               QString *stdOut /* = 0 */, QString *errorMessage)
 {
     typedef QSharedPointer<QTemporaryFile> TemporaryFilePtr;
     typedef QList<TemporaryFilePtr> TemporaryFilePtrList;
-    typedef QMap<QString, QString>::const_iterator FieldConstIterator;
 
     QProcess process;
+    const QString binary = script.front();
     QStringList arguments;
-    // Check on the process
-    const QFileInfo binaryInfo(binary);
-    if (!binaryInfo.isFile()) {
-        *errorMessage = QString::fromLatin1("The Generator script %1 does not exist").arg(binary);
-        return false;
-    }
-#ifdef Q_OS_WIN // Windows: Cannot run scripts by QProcess, do 'cmd /c'
-    const QString extension = binaryInfo.suffix();
-    if (!extension.isEmpty() && extension.compare(QLatin1String("exe"), Qt::CaseInsensitive) != 0) {
-        arguments.push_back(QLatin1String("/C"));
-        arguments.push_back(binary);
-        binary = QString::fromLocal8Bit(qgetenv("COMSPEC"));
-        if (binary.isEmpty())
-            binary = QLatin1String("cmd.exe");
-    }
-#endif // Q_OS_WIN
-    // Arguments
+    const int binarySize = script.size();
+    for (int i = 1; i < binarySize; i++)
+        arguments.push_back(script.at(i));
+
+    // Arguments: Prepend 'dryrun' and do field replacement
     if (dryRun)
-        arguments << QLatin1String("--dry-run");
-    // Turn the field replacement map into a list of arguments "key=value".
-    // Pass on free-format-texts as a temporary files indicated by a colon
-    // separator "key:filename"
-    TemporaryFilePtrList temporaryFiles;
+        arguments.push_back(QLatin1String("--dry-run"));
 
-    const FieldConstIterator cend = fieldMap.constEnd();
-    for (FieldConstIterator it = fieldMap.constBegin(); it != cend; ++it) {
-        const QString &value = it.value();
-        // Is a temporary file required?
-        const bool passAsTemporaryFile = value.contains(QLatin1Char('\n'));
-        if (passAsTemporaryFile) {
-            // Create a file and pass on as "key:filename"
-            TemporaryFilePtr temporaryFile = writeTemporaryFile(value);
-            if (temporaryFile.isNull()) {
-                *errorMessage = QString::fromLatin1("Cannot create temporary file");
-                return false;
-            }
-            temporaryFiles.push_back(temporaryFile);
-            arguments << (it.key() + QLatin1Char(':') + QDir::toNativeSeparators(temporaryFile->fileName()));
-        } else {
-            // Normal value "key=value"
-            arguments << (it.key() + QLatin1Char('=') + value);
-        }
+    // Arguments: Prepend 'dryrun'. Do field replacement to actual
+    // argument value to expand via temporary file if specified
+    CustomWizardContext::TemporaryFilePtrList temporaryFiles;
+    foreach (const GeneratorScriptArgument &argument, argumentsIn) {
+        QString value = argument.value;
+        const bool nonEmptyReplacements
+                = argument.flags & GeneratorScriptArgument::WriteFile ?
+                    CustomWizardContext::replaceFields(fieldMap, &value, &temporaryFiles) :
+                    CustomWizardContext::replaceFields(fieldMap, &value);
+        if (nonEmptyReplacements || !(argument.flags & GeneratorScriptArgument::OmitEmpty))
+            arguments.push_back(value);
     }
     process.setWorkingDirectory(workingDirectory);
     if (CustomWizard::verbose())
@@ -157,13 +149,14 @@ static bool
 // Do a dry run of the generation script to get a list of files
 Core::GeneratedFiles
     dryRunCustomWizardGeneratorScript(const QString &targetPath,
-                                      const QString &script,
+                                      const QStringList &script,
+                                      const QList<GeneratorScriptArgument> &arguments,
                                       const QMap<QString, QString> &fieldMap,
                                       QString *errorMessage)
 {
     // Run in temporary directory as the target path may not exist yet.
     QString stdOut;
-    if (!runGenerationScriptHelper(QDir::tempPath(), script, true,
+    if (!runGenerationScriptHelper(QDir::tempPath(), script, arguments, true,
                              fieldMap, &stdOut, errorMessage))
         return Core::GeneratedFiles();
     Core::GeneratedFiles files;
@@ -199,10 +192,14 @@ Core::GeneratedFiles
     return files;
 }
 
-bool runCustomWizardGeneratorScript(const QString &targetPath, const QString &script,
-                                    const QMap<QString, QString> &fieldMap, QString *errorMessage)
+bool runCustomWizardGeneratorScript(const QString &targetPath,
+                                    const QStringList &script,
+                                    const QList<GeneratorScriptArgument> &arguments,
+                                    const QMap<QString, QString> &fieldMap,
+                                    QString *errorMessage)
 {
-    return runGenerationScriptHelper(targetPath, script, false, fieldMap,
+    return runGenerationScriptHelper(targetPath, script, arguments,
+                                     false, fieldMap,
                                      0, errorMessage);
 }
 
diff --git a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h
index d47168b3f934ae8d4364be6733e3a818047939f9..6010a97e1b01a40d7653202a34ba56564f60e850 100644
--- a/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h
+++ b/src/plugins/projectexplorer/customwizard/customwizardscriptgenerator.h
@@ -31,8 +31,7 @@
 #define CUSTOMWIZARDSCRIPTGENERATOR_H
 
 #include <QtCore/QMap>
-#include <QtCore/QList>
-#include <QtCore/QString>
+#include <QtCore/QStringList>
 
 namespace Core {
 class GeneratedFile;
@@ -41,6 +40,8 @@ class GeneratedFile;
 namespace ProjectExplorer {
 namespace Internal {
 
+struct GeneratorScriptArgument;
+
 /* Custom wizard script generator functions. In addition to the <file> elements
  * that define template files in which macros are replaced, it is possible to have
  * a custom wizard call a generation script (specified in the "generatorscript"
@@ -64,14 +65,21 @@ namespace Internal {
  * should create those, too.
  */
 
+// Parse the script arguments apart and expand the binary.
+QStringList fixGeneratorScript(const QString &configFile, QString attributeIn);
+
 // Step 1) Do a dry run of the generation script to get a list of files on stdout
 QList<Core::GeneratedFile>
-    dryRunCustomWizardGeneratorScript(const QString &targetPath, const QString &script,
+    dryRunCustomWizardGeneratorScript(const QString &targetPath,
+                                      const QStringList &script,
+                                      const QList<GeneratorScriptArgument> &arguments,
                                       const QMap<QString, QString> &fieldMap,
                                       QString *errorMessage);
 
 // Step 2) Generate files
-bool runCustomWizardGeneratorScript(const QString &targetPath, const QString &script,
+bool runCustomWizardGeneratorScript(const QString &targetPath,
+                                    const QStringList &script,
+                                    const QList<GeneratorScriptArgument> &arguments,
                                     const QMap<QString, QString> &fieldMap,
                                     QString *errorMessage);