Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refresh to .NET 4.8, add new cli parameter -PerUser... #27

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ local.properties
## TODO: If you have NuGet Package Restore enabled, uncomment this
packages/
Debug/
Release/

# Visual C++ cache files
ipch/
Expand Down Expand Up @@ -116,7 +117,7 @@ _UpgradeReport_Files/
Backup*/
UpgradeLog*.XML


.vs/

############
## Windows
Expand Down
33 changes: 11 additions & 22 deletions Paraffin/ArgParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
// </Project>
//------------------------------------------------------------------------------

using System;
using System.Diagnostics;

namespace Wintellect.Paraffin
{
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;

/// <summary>
/// A command line argument parsing class.
/// </summary>
Expand All @@ -22,9 +21,9 @@ namespace Wintellect.Paraffin
/// <para>
/// There are two arrays of flags you'll pass to the constructors. The
/// flagSymbols are supposed to be standalone switches that toggle an option
/// on. The dataSymbols are for switches that take data values. For
/// example, if your application needs a switch, -c, to set the count,
/// you'd put "c" in the dataSymbols. This code will allow both "-c100" and
/// on. The dataSymbols are for switches that take data values. For
/// example, if your application needs a switch, -c, to set the count,
/// you'd put "c" in the dataSymbols. This code will allow both "-c100" and
/// the usual "-c" "100" both to be passed on the command line. Note that
/// you can pass null/Nothing for dataSymbols if you don't need them.
/// </para>
Expand All @@ -45,11 +44,11 @@ internal abstract class ArgParser
private readonly Boolean caseSensitiveSwitches;

/// <summary>
/// Initializes a new instance of the ArgParser class and defaults to
/// Initializes a new instance of the ArgParser class and defaults to
/// "/" and "-" as the only valid switch characters
/// </summary>
/// <param name="flagSymbols">
/// The array of simple flags to toggle options on or off.
/// The array of simple flags to toggle options on or off.
/// </param>
/// <param name="dataSymbols">
/// The array of options that need data either in the next parameter or
Expand All @@ -58,11 +57,6 @@ internal abstract class ArgParser
/// <param name="caseSensitiveSwitches">
/// True if case sensitive switches are supposed to be used.
/// </param>
[SuppressMessage("Microsoft.Naming",
"CA1726:UsePreferredTerms",
MessageId = "flag",
Justification = "Flag is appropriate term when " +
"dealing with command line arguments.")]
protected ArgParser(String[] flagSymbols,
String[] dataSymbols,
Boolean caseSensitiveSwitches)
Expand Down Expand Up @@ -94,11 +88,6 @@ protected ArgParser(String[] flagSymbols,
/// Thrown if <paramref name="flagSymbols"/> or
/// <paramref name="switchChars"/> are invalid.
/// </exception>
[SuppressMessage("Microsoft.Naming",
"CA1726:UsePreferredTerms",
MessageId = "flag",
Justification = "Flag is appropriate term when " +
"dealing with command line arguments.")]
protected ArgParser(String[] flagSymbols,
String[] dataSymbols,
Boolean caseSensitiveSwitches,
Expand All @@ -117,7 +106,7 @@ protected ArgParser(String[] flagSymbols,
if ((null == flagSymbols) || (0 == flagSymbols.Length))
{
throw new ArgumentException(Constants.ArrayMustBeValid,
"flagSymbols");
nameof(flagSymbols));
}

Debug.Assert(null != switchChars, "null != switchChars");
Expand All @@ -133,7 +122,7 @@ protected ArgParser(String[] flagSymbols,
if ((null == switchChars) || (0 == switchChars.Length))
{
throw new ArgumentException(Constants.ArrayMustBeValid,
"switchChars");
nameof(switchChars));
}

this.flagSymbols = flagSymbols;
Expand Down Expand Up @@ -178,7 +167,7 @@ protected enum SwitchStatus
/// The string array to parse through.
/// </param>
/// <returns>
/// True if parsing was correct.
/// True if parsing was correct.
/// </returns>
/// <exception cref="ArgumentException">
/// Thrown if <paramref name="args"/> is null.
Expand Down
2 changes: 1 addition & 1 deletion Paraffin/Constants.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Paraffin/Constants.resx
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ Optional parameters when creating a new fragment:
-Permanent - Sets Permanent="Yes" on all file elements.
-WiX4 - Create fragments compatible with WiX 4, defaults to
WiX 3.
-PerUser - Supports Limited Privileges / Per User MSI by adding
a Registry Value Key Path to each File's Component.

Required parameters to update a previously created file for major upgrades.
If you delete an input file, using -update will delete the Component and File
Expand Down
24 changes: 15 additions & 9 deletions Paraffin/Main.Create.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace Wintellect.Paraffin
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
Expand Down Expand Up @@ -86,7 +87,7 @@ private static void RecurseDirectoriesForNewFile(XElement currElement,
// That means I'll be adding files to the <DirectoryRef> node, which
// has been passed in the currElement.
XElement addToNode = currElement;
if (argValues.NoRootDirectoryState == false)
if (!argValues.NoRootDirectoryState)
{
// It's new so create a Directory element.
XElement directoryNode = CreateDirectoryElement(directory);
Expand All @@ -109,10 +110,10 @@ private static void RecurseDirectoriesForNewFile(XElement currElement,
AddNewFilesToDirectoryNode(directory, addToNode);

// Recurse the directories if I'm supposed to do so.
if (false == argValues.NoRecursion)
if (!argValues.NoRecursion)
{
String[] dirs = Directory.GetDirectories(directory);
foreach (var item in dirs)
foreach (String item in dirs)
{
Boolean skipDirectory = IsDirectoryExcluded(item);
if (false == skipDirectory)
Expand All @@ -137,11 +138,9 @@ private static void RecurseDirectoriesForNewFile(XElement currElement,
private static void AddNewFilesToDirectoryNode(String directory,
XElement directoryElem)
{
var filesQuery = ProcessedDirectoryFiles(directory);

// Only do the work if there are some files in the directory.
var files = filesQuery as String[] ?? filesQuery.ToArray();
if (!files.Any())
IEnumerable<String> filesQuery = ProcessedDirectoryFiles(directory);
String[] files = filesQuery as String[] ?? filesQuery.ToArray();
if (files.Length == 0)
{
return;
}
Expand All @@ -150,12 +149,19 @@ private static void AddNewFilesToDirectoryNode(String directory,
XElement currentComponent = CreateComponentElement();

// For each file on disk.
foreach (var file in files)
foreach (String file in files)
{
// Create the File element and add it to the current
// Component element.
XElement fileElement = CreateFileElement(file);
currentComponent.Add(fileElement);

if (argValues.PerUser)
{
XElement registryValueElement = CreateRegistryValueElement(file);
currentComponent.Add(registryValueElement);
}

directoryElem.Add(currentComponent);
currentComponent = CreateComponentElement();
}
Expand Down
23 changes: 20 additions & 3 deletions Paraffin/Main.Update.cs
Original file line number Diff line number Diff line change
Expand Up @@ -363,10 +363,14 @@ private static void UpdateFilesInDirectoryNode(String directory,
// file so just add it. First create a new File
// element.
XElement fileElement = CreateFileElement(file);

// Add the file to this component.
compElement.Add(fileElement);

if (argValues.PerUser)
{
XElement registryValueElement = CreateRegistryValueElement(file);
compElement.Add(registryValueElement);
}

// Add this element to the directory.
addToElement.Add(compElement);
}
Expand Down Expand Up @@ -585,7 +589,7 @@ private static void FixKeyPathAttribute(String file,
XElement compElement)
{
var attrib = fileElement.Attribute("KeyPath");
if (attrib == null)
if (attrib == null && !argValues.PerUser) // When PerUser, KeyPath is stored on a RegistryValue
{
fileElement.Add(
new XAttribute("KeyPath", "yes"));
Expand Down Expand Up @@ -784,6 +788,19 @@ private static Boolean InitializeArgumentsFromFile(String inputXml)
RegexOptions.IgnoreCase));
}

var perUserUsage = options.Descendants(PERUSER);
if (perUserUsage.Count() == 1)
{
String rawValue = perUserUsage.First().Value;
if (0 == String.Compare(rawValue,
"true",
StringComparison.OrdinalIgnoreCase))
{
argValues.PerUser = true;
}
}


// Now that everything is read out of the original options block,
// add in any additional -ext, -dirExclude, and -regExExclude
// options specified on the command line.
Expand Down
50 changes: 48 additions & 2 deletions Paraffin/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ internal static partial class Program
private const String REGEXEXITEMELEM = "RegEx";
private const String PERMANENT = "Permanent";
private const String WIX4 = "WiX4";
private const String PERUSER = "PerUser";
#endregion

// The PE file extensions.
Expand Down Expand Up @@ -465,7 +466,8 @@ private static void AddCommandLineOptionsComment(XElement wixElement)
new XElement(NODIRECTORYELEM, argValues.NoRootDirectory),
new XElement(DISKIDELEM, argValues.DiskId),
new XElement(PERMANENT, argValues.Permanent),
new XElement(WIX4, argValues.WiX4)
new XElement(WIX4, argValues.WiX4),
new XElement(PERUSER, argValues.PerUser)
);

// Add the file extension exclusions.
Expand Down Expand Up @@ -819,13 +821,57 @@ private static XElement CreateFileElement(String fileName)
file.Add(new XAttribute("Checksum", "yes"));
}

file.Add(new XAttribute("KeyPath", "yes"));
if (!argValues.PerUser)
{
file.Add(new XAttribute("KeyPath", "yes"));
}

fileName = AliasedFilename(fileName);
file.Add(new XAttribute("Source", fileName));
return file;
}

/// <summary>
/// Creates a RegistryValue element for the file in <paramref name="fileName"/>.
/// This is to facilitate LimitedPrivilige/PerUser MSI creation
/// </summary>
/// <param name="fileName">
/// The full filename to process.
/// </param>
/// <returns>
/// A valid <see cref="XElement"/> for the RegistryValue element.
/// </returns>
private static XElement CreateRegistryValueElement(String fileName)
{
String fileId;
if (argValues.Version == Version1File)
{
// Create a unique filename. In a one file per component run,
// this will mean that the file and it's parent component will
// have the same number.
fileId = CreateSeventyCharIdString("file",
argValues.GroupName,
componentNumber - 1);
}
else
{
Guid g = Guid.NewGuid();
fileId = String.Format(CultureInfo.InvariantCulture,
"file_{0}",
g.ToString("N").ToUpper(CultureInfo.InvariantCulture));
}

XElement registryValue = new XElement(argValues.WixNamespace + "RegistryValue");
registryValue.Add(new XAttribute("Root", "HKCU"));
registryValue.Add(new XAttribute("Key", "Software\\Tolt Technologies\\Ability Drive\\InstalledFiles"));
registryValue.Add(new XAttribute("Name", fileId));
registryValue.Add(new XAttribute("Value", ""));
registryValue.Add(new XAttribute("Type", "string"));
registryValue.Add(new XAttribute("KeyPath", "yes"));

return registryValue;
}

/// <summary>
/// Creates a standard Component element.
/// </summary>
Expand Down
8 changes: 5 additions & 3 deletions Paraffin/Paraffin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Wintellect.Paraffin</RootNamespace>
<AssemblyName>Paraffin</AssemblyName>
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SignAssembly>false</SignAssembly>
<AssemblyOriginatorKeyFile>
Expand Down Expand Up @@ -52,7 +52,7 @@
</DocumentationFile>
<RunCodeAnalysis>true</RunCodeAnalysis>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<CodeAnalysisRuleSet>ParaffinRuleSet.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>Paraffin.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
Expand All @@ -68,7 +68,7 @@
</DocumentationFile>
<RunCodeAnalysis>true</RunCodeAnalysis>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<CodeAnalysisRuleSet>Migrated rules for Paraffin.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet>Paraffin.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
Expand Down Expand Up @@ -108,7 +108,9 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="Paraffin.ruleset" />
<None Include="ParaffinRuleSet.ruleset" />
</ItemGroup>
<ItemGroup>
Expand Down
20 changes: 20 additions & 0 deletions Paraffin/Paraffin.ruleset
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Rules for Paraffin" Description="Code analysis rules for Paraffin.csproj." ToolsVersion="17.0">
<IncludeAll Action="Warning" />
<Rules AnalyzerId="Wintellect.Analyzers" RuleNamespace="Wintellect.Analyzers">
<Rule Id="Wintellect001" Action="None" />
<Rule Id="Wintellect002" Action="None" />
<Rule Id="Wintellect003" Action="None" />
<Rule Id="Wintellect004" Action="None" />
<Rule Id="Wintellect005" Action="None" />
<Rule Id="Wintellect006" Action="None" />
<Rule Id="Wintellect007" Action="None" />
<Rule Id="Wintellect008" Action="None" />
<Rule Id="Wintellect009" Action="None" />
<Rule Id="Wintellect010" Action="None" />
<Rule Id="Wintellect011" Action="None" />
<Rule Id="Wintellect012" Action="None" />
<Rule Id="Wintellect013" Action="None" />
<Rule Id="Wintellect014" Action="None" />
</Rules>
</RuleSet>
Loading