diff --git a/.gitignore b/.gitignore
index c19742c237..143c3c0a90 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,4 +50,4 @@ gen
.profile.ps1
#VS Code files
-/.vscode
+.vscode
diff --git a/build.psm1 b/build.psm1
index a87ccd54ac..bfaddc1961 100644
--- a/build.psm1
+++ b/build.psm1
@@ -1276,22 +1276,17 @@ function Start-ResGen
[CmdletBinding()]
param()
- Get-ChildItem $PSScriptRoot/src -Directory | ? {
- Get-ChildItem (Join-Path $_.FullName 'resources') -ErrorAction SilentlyContinue} | % {
- $_. Name} | % {
+ # Add .NET CLI tools to PATH
+ Find-Dotnet
- $module = $_
- Get-ChildItem "$PSScriptRoot/src/$module/resources" -Filter '*.resx' | % {
- $className = $_.Name.Replace('.resx', '')
- $xml = [xml](Get-Content -raw $_.FullName)
-
- $fileName = $className
- $genSource = Get-StronglyTypeCsFileForResx -xml $xml -ModuleName $module -ClassName $className
- $outPath = "$PSScriptRoot/src/$module/gen/$fileName.cs"
- Write-Verbose "ResGen for $outPath"
- New-Item -Type Directory -ErrorAction SilentlyContinue (Split-Path $outPath) > $null
- Set-Content -Encoding Ascii -Path $outPath -Value $genSource
- }
+ Push-Location "$PSScriptRoot/src/ResGen"
+ try
+ {
+ Start-NativeExecution { dotnet run } | Write-Verbose
+ }
+ finally
+ {
+ Pop-Location
}
}
@@ -1576,129 +1571,6 @@ function script:Start-NativeExecution([scriptblock]$sb)
}
}
-function script:Get-StronglyTypeCsFileForResx
-{
- param($xml, $ModuleName, $ClassName)
-
- # Example
- #
- # $ClassName = Full.Name.Of.The.ClassFoo
- # $shortClassName = ClassFoo
- # $namespaceName = Full.Name.Of.The
-
- $shortClassName = $ClassName
- $namespaceName = $null
-
- $lastIndexOfDot = $className.LastIndexOf(".")
- if ($lastIndexOfDot -ne -1)
- {
- $namespaceName = $className.Substring(0, $lastIndexOfDot)
- $shortClassName = $className.Substring($lastIndexOfDot + 1)
- }
-
-$banner = @'
-//------------------------------------------------------------------------------
-//
-// This code was generated by a Start-ResGen funciton from build.psm1.
-// To add or remove a member, edit your .ResX file then rerun Start-ResGen.
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-{0}
-'@
-
-$namespace = @'
-namespace {0} {{
-{1}
-}}
-'@
-
-$body = @'
-using System;
-using System.Reflection;
-
-///
-/// A strongly-typed resource class, for looking up localized strings, etc.
-///
-[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
-[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-
-internal class {0} {{
-
- private static global::System.Resources.ResourceManager resourceMan;
-
- private static global::System.Globalization.CultureInfo resourceCulture;
-
- [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
- internal {0}() {{
- }}
-
- ///
- /// Returns the cached ResourceManager instance used by this class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Resources.ResourceManager ResourceManager {{
- get {{
- if (object.ReferenceEquals(resourceMan, null)) {{
- global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("{1}.resources.{3}", typeof({0}).GetTypeInfo().Assembly);
- resourceMan = temp;
- }}
- return resourceMan;
- }}
- }}
-
- ///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
- ///
- [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
- internal static global::System.Globalization.CultureInfo Culture {{
- get {{
- return resourceCulture;
- }}
- set {{
- resourceCulture = value;
- }}
- }}
- {2}
-}}
-'@
-
- $entry = @'
-
- ///
- /// Looks up a localized string similar to {1}
- ///
- internal static string {0} {{
- get {{
- return ResourceManager.GetString("{0}", resourceCulture);
- }}
- }}
-'@
- $entries = $xml.root.data | % {
- if ($_) {
- $val = $_.value.Replace("`n", "`n ///")
- $name = $_.name.Replace(' ', '_')
- $entry -f $name,$val
- }
- } | Out-String
-
- $bodyCode = $body -f $shortClassName,$ModuleName,$entries,$ClassName
-
- if ($NamespaceName)
- {
- $bodyCode = $namespace -f $NamespaceName, $bodyCode
- }
-
- $resultCode = $banner -f $bodyCode
-
- return $resultCode -replace "`r`n?|`n","`r`n"
-}
-
# Builds coming out of this project can have version number as 'a.b.c' OR 'a.b.c-d-f'
# This function converts the above version into major.minor[.build[.revision]] format
function Get-PackageVersionAsMajorMinorBuildRevision
diff --git a/src/ResGen/Program.cs b/src/ResGen/Program.cs
new file mode 100644
index 0000000000..fe7524c8de
--- /dev/null
+++ b/src/ResGen/Program.cs
@@ -0,0 +1,159 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Xml.Linq;
+
+namespace ConsoleApplication
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ // we are assuming resgen is run with 'dotnet run'
+ // so we can use relative paths
+ foreach (string folder in Directory.EnumerateDirectories(".."))
+ {
+ string moduleName = Path.GetFileName(folder);
+ string resourcePath = Path.Combine(folder, "resources");
+ if (Directory.Exists(resourcePath))
+ {
+ string genFolder = Path.Combine(folder, "gen");
+ if (!Directory.Exists(genFolder))
+ {
+ Directory.CreateDirectory(genFolder);
+ }
+
+ foreach (string resxPath in Directory.EnumerateFiles(resourcePath, "*.resx"))
+ {
+ string className = Path.GetFileNameWithoutExtension(resxPath);
+ string sourceCode = GetStronglyTypeCsFileForResx(resxPath, moduleName, className);
+ string outPath = Path.Combine(genFolder, className + ".cs");
+ Console.WriteLine("ResGen for " + outPath);
+ File.WriteAllText(outPath, sourceCode);
+ }
+ }
+ }
+ }
+
+ private static string GetStronglyTypeCsFileForResx(string xmlPath, string moduleName, string className)
+ {
+ // Example
+ //
+ // className = Full.Name.Of.The.ClassFoo
+ // shortClassName = ClassFoo
+ // namespaceName = Full.Name.Of.The
+
+ string shortClassName = className;
+ string namespaceName = null;
+ int lastIndexOfDot = className.LastIndexOf('.');
+ if (lastIndexOfDot != -1)
+ {
+ namespaceName = className.Substring(0, lastIndexOfDot);
+ shortClassName = className.Substring(lastIndexOfDot + 1);
+ }
+
+ var entries = new StringBuilder();
+ XElement root = XElement.Parse(File.ReadAllText(xmlPath));
+ foreach (var data in root.Elements("data"))
+ {
+ string value = data.Value.Replace("\n", "\n ///");
+ string name = data.Attribute("name").Value.Replace(' ', '_');
+ entries.AppendFormat(ENTRY, name, value);
+ }
+
+ string bodyCode = string.Format(BODY, shortClassName, moduleName, entries.ToString(), className);
+ if (namespaceName != null)
+ {
+ bodyCode = string.Format(NAMESPACE, namespaceName, bodyCode);
+ }
+
+ string resultCode = string.Format(BANNER, bodyCode).Replace("\r\n?|\n", "\r\n");
+ return resultCode;
+ }
+
+ private static readonly string BANNER = @"
+//------------------------------------------------------------------------------
+//
+// This code was generated by a dotnet run from src\ResGen folder.
+// To add or remove a member, edit your .resx file then rerun src\ResGen.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+{0}
+";
+
+ private static readonly string NAMESPACE = @"
+namespace {0} {{
+{1}
+}}
+";
+ private static readonly string BODY = @"
+using System;
+using System.Reflection;
+
+///
+/// A strongly-typed resource class, for looking up localized strings, etc.
+///
+[global::System.CodeDom.Compiler.GeneratedCodeAttribute(""System.Resources.Tools.StronglyTypedResourceBuilder"", ""4.0.0.0"")]
+[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+
+internal class {0} {{
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(""Microsoft.Performance"", ""CA1811:AvoidUncalledPrivateCode"")]
+ internal {0}() {{
+ }}
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {{
+ get {{
+ if (object.ReferenceEquals(resourceMan, null)) {{
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(""{1}.resources.{3}"", typeof({0}).GetTypeInfo().Assembly);
+ resourceMan = temp;
+ }}
+ return resourceMan;
+ }}
+ }}
+
+ ///
+ /// Overrides the current threads CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {{
+ get {{
+ return resourceCulture;
+ }}
+ set {{
+ resourceCulture = value;
+ }}
+ }}
+ {2}
+}}
+";
+
+ private static readonly string ENTRY = @"
+
+ ///
+ /// Looks up a localized string similar to {1}
+ ///
+ internal static string {0} {{
+ get {{
+ return ResourceManager.GetString(""{0}"", resourceCulture);
+ }}
+ }}
+";
+
+ }
+}
diff --git a/src/ResGen/project.json b/src/ResGen/project.json
new file mode 100644
index 0000000000..0dea62d8e4
--- /dev/null
+++ b/src/ResGen/project.json
@@ -0,0 +1,28 @@
+{
+ "name": "resgen",
+ "version": "1.0.0-*",
+ "description": "Generates C# typed bindings for .resx files",
+
+ "buildOptions": {
+ "emitEntryPoint": true
+ },
+
+ "frameworks": {
+ "netcoreapp1.0": {
+ "dependencies": {
+ "Microsoft.NETCore.App": "1.0.0",
+ "System.Xml.XDocument": "4.0.11"
+ }
+ }
+ },
+
+ "runtimes": {
+ "ubuntu.14.04-x64": { },
+ "debian.8-x64": { },
+ "centos.7-x64": { },
+ "win7-x64": { },
+ "win81-x64": { },
+ "win10-x64": { },
+ "osx.10.11-x64": { }
+ }
+}