diff --git a/src/ElectronNET.Build/ElectronNET.Build.csproj b/src/ElectronNET.Build/ElectronNET.Build.csproj
new file mode 100644
index 0000000..5b6931a
--- /dev/null
+++ b/src/ElectronNET.Build/ElectronNET.Build.csproj
@@ -0,0 +1,35 @@
+
+
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+ <_DllTargetPath>$(MSBuildThisFileDirectory)\..\ElectronNET\build
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/ElectronNET.Build/ElectronNET.Build.csproj.DotSettings b/src/ElectronNET.Build/ElectronNET.Build.csproj.DotSettings
new file mode 100644
index 0000000..89316e4
--- /dev/null
+++ b/src/ElectronNET.Build/ElectronNET.Build.csproj.DotSettings
@@ -0,0 +1,2 @@
+
+ Library
\ No newline at end of file
diff --git a/src/ElectronNET.Build/PrintItemMetadata.cs b/src/ElectronNET.Build/PrintItemMetadata.cs
new file mode 100644
index 0000000..2cce179
--- /dev/null
+++ b/src/ElectronNET.Build/PrintItemMetadata.cs
@@ -0,0 +1,39 @@
+namespace ElectronNET.Build
+{
+ using System;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
+
+ public class DumpItemMetadataTask : Task
+ {
+ // The item group whose metadata will be dumped.
+ [Required]
+ public ITaskItem[] Items { get; set; }
+
+ public override bool Execute()
+ {
+ try
+ {
+ foreach (var item in this.Items)
+ {
+ // Log the item's identity (the Include attribute)
+ this.Log.LogMessage(MessageImportance.High, $"Item: {item.ItemSpec}");
+
+ // Iterate through each metadata field of the item.
+ foreach (string metadataName in item.MetadataNames)
+ {
+ string metadataValue = item.GetMetadata(metadataName);
+ this.Log.LogMessage(MessageImportance.High, $" {metadataName}: {metadataValue}");
+ }
+ }
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ this.Log.LogErrorFromException(ex);
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ElectronNET.Build/RemoveEnvironmentVariables.cs b/src/ElectronNET.Build/RemoveEnvironmentVariables.cs
new file mode 100644
index 0000000..2840e9b
--- /dev/null
+++ b/src/ElectronNET.Build/RemoveEnvironmentVariables.cs
@@ -0,0 +1,42 @@
+namespace ElectronNET.Build
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Linq;
+ using System.Text.RegularExpressions;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
+
+ public class RemoveEnvironmentVariables : Task
+ {
+ [Required]
+ public string Variables { get; set; }
+
+ public override bool Execute()
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(this.Variables))
+ {
+ this.Log.LogError("The Variables property is not set");
+ return false;
+ }
+
+ var items = this.Variables.Split(new[] { ':', ';', ',' }, StringSplitOptions.RemoveEmptyEntries);
+ foreach (var item in items)
+ {
+ Environment.SetEnvironmentVariable(item.Trim(), null);
+ this.Log.LogMessage("Unset environment variable: {0}", item);
+ }
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ this.Log.LogErrorFromException(ex);
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ElectronNET.Build/ReplaceMsBuildPropertiesTask.cs b/src/ElectronNET.Build/ReplaceMsBuildPropertiesTask.cs
new file mode 100644
index 0000000..30e7d65
--- /dev/null
+++ b/src/ElectronNET.Build/ReplaceMsBuildPropertiesTask.cs
@@ -0,0 +1,83 @@
+namespace ElectronNET.Build
+{
+ using System;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Text.RegularExpressions;
+ using Microsoft.Build.Framework;
+ using Microsoft.Build.Utilities;
+
+ public class ReplaceTemplateTask : Task
+ {
+ [Required]
+ public string TemplateFile { get; set; }
+
+ [Required]
+ public string OutputFile { get; set; }
+
+ [Required]
+ public ITaskItem[] TemplateProperties { get; set; }
+
+ public override bool Execute()
+ {
+ try
+ {
+ ////var props = this.BuildEngine9.GetGlobalProperties();
+
+ ////var globalProperties = props
+ //// .Select(e => string.Format("{0}: {1}", e.Key, e.Value));
+
+ ////this.Log.LogMessage(MessageImportance.High, "Global Properties: \r\n" + string.Join(Environment.NewLine, globalProperties));
+
+ ////var envVariables = Environment.GetEnvironmentVariables();
+ ////var envList = new List();
+ ////foreach (var v in envVariables.Keys)
+ ////{
+ //// envList.Add(string.Format("{0}: {1}", v, envVariables[v]));
+ ////}
+
+ ////this.Log.LogMessage(MessageImportance.High, "Environment Variables: \r\n" + string.Join(Environment.NewLine, envList));
+
+ string content = File.ReadAllText(this.TemplateFile);
+
+ // Build a dictionary of property names and values.
+ var dict = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ foreach (var item in this.TemplateProperties)
+ {
+ dict[item.ItemSpec] = item.GetMetadata("Value").Replace("\\", "\\\\");
+ }
+
+ // Regex pattern to match placeholders like $(PropertyName)
+ string pattern = @"\$\((?\w+)\)";
+ content = Regex.Replace(content, pattern, match =>
+ {
+ string propName = match.Groups["prop"].Value;
+ return dict.TryGetValue(propName, out var value) ? value : match.Value;
+ });
+
+ // Check if the output file exists and read its content
+ if (File.Exists(this.OutputFile))
+ {
+ string existingContent = File.ReadAllText(this.OutputFile);
+ // Only write the file if the content has changed
+ if (existingContent != content)
+ {
+ File.WriteAllText(this.OutputFile, content);
+ }
+ }
+ else
+ {
+ // Write the transformed content to the output file if it doesn't exist
+ File.WriteAllText(this.OutputFile, content);
+ }
+
+ return true;
+ }
+ catch (Exception ex)
+ {
+ this.Log.LogErrorFromException(ex);
+ return false;
+ }
+ }
+ }
+}
\ No newline at end of file