diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..ff9df19 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,28 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceRoot}/ElectronNET.CLI/bin/Debug/netcoreapp2.0/dotnet-electronize.dll", + "args": [], + "cwd": "${workspaceRoot}/ElectronNET.CLI", + // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window + "console": "internalConsole", + "stopAtEntry": false, + "internalConsoleOptions": "openOnSessionStart" + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..03e64bf --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,16 @@ +{ + "version": "0.1.0", + "command": "dotnet", + "isShellCommand": true, + "args": [], + "tasks": [ + { + "taskName": "build", + "args": [ + "${workspaceRoot}/ElectronNET.CLI/ElectronNET.CLI.csproj" + ], + "isBuildCommand": true, + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/ElectronNET.API/ElectronNET.API.csproj b/ElectronNET.API/ElectronNET.API.csproj index 104a13b..04863a3 100644 --- a/ElectronNET.API/ElectronNET.API.csproj +++ b/ElectronNET.API/ElectronNET.API.csproj @@ -12,5 +12,9 @@ + + + + diff --git a/ElectronNET.API/devCleanup.cmd b/ElectronNET.API/devCleanup.cmd index 294a54c..1ea3754 100644 --- a/ElectronNET.API/devCleanup.cmd +++ b/ElectronNET.API/devCleanup.cmd @@ -1 +1 @@ -rd /s /q "%userprofile%\.nuget\packages\electronnet.api\" +rd /s /q %userprofile%\.nuget\packages\electronnet.api 2>nul diff --git a/ElectronNET.CLI/Commands/BuildCommand.cs b/ElectronNET.CLI/Commands/BuildCommand.cs index 66503b9..682e07a 100644 --- a/ElectronNET.CLI/Commands/BuildCommand.cs +++ b/ElectronNET.CLI/Commands/BuildCommand.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Runtime.InteropServices; using System.Threading.Tasks; namespace ElectronNET.CLI.Commands @@ -16,23 +17,43 @@ namespace ElectronNET.CLI.Commands { return Task.Run(() => { - Console.WriteLine("Build Windows Application..."); + Console.WriteLine("Build Electron Application..."); string tempPath = Path.Combine(Directory.GetCurrentDirectory(), "obj", "desktop"); Console.WriteLine("Executing dotnet publish in this directory: " + tempPath); string tempBinPath = Path.Combine(tempPath, "bin"); - ProcessHelper.CmdExecute($"dotnet publish -r win10-x64 --output \"{tempBinPath}\"", Directory.GetCurrentDirectory()); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Console.WriteLine("Build ASP.NET Core App for Windows..."); + + ProcessHelper.CmdExecute($"dotnet publish -r win10-x64 --output \"{tempBinPath}\"", Directory.GetCurrentDirectory()); + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Console.WriteLine("Build ASP.NET Core App for OSX..."); + + ProcessHelper.CmdExecute($"dotnet publish -r osx-x64 --output \"{tempBinPath}\"", Directory.GetCurrentDirectory()); + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Console.WriteLine("Build ASP.NET Core App for Linux (Ubuntu x64)..."); + + ProcessHelper.CmdExecute($"dotnet publish -r ubuntu-x64 --output \"{tempBinPath}\"", Directory.GetCurrentDirectory()); + } if (Directory.Exists(tempPath) == false) { Directory.CreateDirectory(tempPath); } - EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "main.js"); - EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "package.json"); - EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "package-lock.json"); + EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "main.js", "ElectronHost."); + EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "package.json", "ElectronHost."); + EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "package-lock.json", "ElectronHost."); string hostApiFolder = Path.Combine(tempPath, "api"); if (Directory.Exists(hostApiFolder) == false) @@ -51,14 +72,44 @@ namespace ElectronNET.CLI.Commands ProcessHelper.CmdExecute("npm install", tempPath); Console.WriteLine("Start npm install electron-packager..."); - ProcessHelper.CmdExecute("npm install electron-packager --global", tempPath); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Works proper on Windows... + ProcessHelper.CmdExecute("npm install electron-packager --global", tempPath); + } + else + { + // ToDo: find another solution or document it proper + // GH Issue https://github.com/electron-userland/electron-prebuilt/issues/48 + Console.WriteLine("Electron Packager - make sure you invoke 'sudo npm install electron - packager--global' at " + tempPath + " manually. Sry."); + } Console.WriteLine("Build Electron Desktop Application..."); string buildPath = Path.Combine(Directory.GetCurrentDirectory(), "bin", "desktop"); Console.WriteLine("Executing electron magic in this directory: " + buildPath); - // Need a solution for --asar support - ProcessHelper.CmdExecute($"electron-packager . --platform=win32 --arch=x64 --out=\"{buildPath}\" --overwrite", tempPath); + // ToDo: Need a solution for --asar support + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Console.WriteLine("Package Electron App for Windows..."); + + ProcessHelper.CmdExecute($"electron-packager . --platform=win32 --arch=x64 --out=\"{buildPath}\" --overwrite", tempPath); + } + + if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Console.WriteLine("Package Electron App for OSX..."); + + ProcessHelper.CmdExecute($"electron-packager . --platform=darwin --arch=x64 --out=\"{buildPath}\" --overwrite", tempPath); + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Console.WriteLine("Package Electron App for Linux..."); + + ProcessHelper.CmdExecute($"electron-packager . --platform=linux --arch=x64 --out=\"{buildPath}\" --overwrite", tempPath); + } return true; }); diff --git a/ElectronNET.CLI/Commands/InitCommand.cs b/ElectronNET.CLI/Commands/InitCommand.cs new file mode 100644 index 0000000..6cfbfe1 --- /dev/null +++ b/ElectronNET.CLI/Commands/InitCommand.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace ElectronNET.CLI.Commands +{ + public class InitCommand : ICommand + { + public const string COMMAND_NAME = "init"; + public const string COMMAND_DESCRIPTION = "Creates the needed Electron.NET config for your Electron Application."; + public const string COMMAND_ARGUMENTS = " from ASP.NET Core Project."; + public static IList CommandOptions { get; set; } = new List(); + + private const string ConfigName = "electronnet.json"; + + public Task ExecuteAsync() + { + return Task.Run(() => + { + var currentDirectory = Directory.GetCurrentDirectory(); + + Console.WriteLine("Adding our config file to your project..."); + + var targetFilePath = Path.Combine(currentDirectory, ConfigName); + + if (File.Exists(targetFilePath)) + { + Console.WriteLine("Config file already in your project."); + return false; + } + + // Deploy config file + EmbeddedFileHelper.DeployEmbeddedFile(currentDirectory, ConfigName); + + // search .csproj + Console.WriteLine($"Search your .csproj to add the needed {ConfigName}..."); + var projectFile = Directory.EnumerateFiles(currentDirectory, "*.csproj", SearchOption.TopDirectoryOnly).FirstOrDefault(); + + // update config file with the name of the csproj + // ToDo: If the csproj name != application name, this will fail + string text = File.ReadAllText(targetFilePath); + text = text.Replace("{{executable}}", Path.GetFileNameWithoutExtension(projectFile)); + File.WriteAllText(targetFilePath, text); + + Console.WriteLine($"Found your .csproj: {projectFile} - check for existing config or update it."); + + using (var stream = File.Open(projectFile, FileMode.OpenOrCreate, FileAccess.ReadWrite)) + { + var xmlDocument = XDocument.Load(stream); + + var projectElement = xmlDocument.Descendants("Project").FirstOrDefault(); + if (projectElement == null || projectElement.Attribute("Sdk")?.Value != "Microsoft.NET.Sdk.Web") + { + Console.WriteLine($"Project file is not a compatible type of 'Microsoft.NET.Sdk.Web'. Your project: {projectElement?.Attribute("Sdk")?.Value}"); + return false; + } + + if (xmlDocument.ToString().Contains($"Content Update=\"{ConfigName}\"")) + { + Console.WriteLine($"{ConfigName} already in csproj."); + return false; + } + + Console.WriteLine($"{ConfigName} will be added to csproj."); + + string itemGroupXmlString = "" + + "" + + "PreserveNewest" + + "" + + ""; + + var newItemGroupForConfig = XElement.Parse(itemGroupXmlString); + xmlDocument.Root.Add(newItemGroupForConfig); + + stream.SetLength(0); + stream.Position = 0; + + xmlDocument.Save(stream); + + Console.WriteLine($"{ConfigName} added in csproj - happy electronizing!"); + } + + return true; + }); + } + + + } +} diff --git a/ElectronNET.CLI/Commands/StartElectronCommand.cs b/ElectronNET.CLI/Commands/StartElectronCommand.cs index 474e1da..1bf7231 100644 --- a/ElectronNET.CLI/Commands/StartElectronCommand.cs +++ b/ElectronNET.CLI/Commands/StartElectronCommand.cs @@ -49,9 +49,9 @@ namespace ElectronNET.CLI.Commands string tempBinPath = Path.Combine(tempPath, "bin"); ProcessHelper.CmdExecute($"dotnet publish -r win10-x64 --output \"{tempBinPath}\"", aspCoreProjectPath); - EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "main.js"); - EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "package.json"); - EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "package-lock.json"); + EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "main.js", "ElectronHost."); + EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "package.json", "ElectronHost."); + EmbeddedFileHelper.DeployEmbeddedFile(tempPath, "package-lock.json", "ElectronHost."); string hostApiFolder = Path.Combine(tempPath, "api"); if (Directory.Exists(hostApiFolder) == false) diff --git a/ElectronNET.CLI/ElectronNET.CLI.csproj b/ElectronNET.CLI/ElectronNET.CLI.csproj index 994d6f5..ed3a5a0 100644 --- a/ElectronNET.CLI/ElectronNET.CLI.csproj +++ b/ElectronNET.CLI/ElectronNET.CLI.csproj @@ -15,6 +15,7 @@ + @@ -24,6 +25,7 @@ + @@ -45,5 +47,8 @@ + + + diff --git a/ElectronNET.CLI/EmbeddedFileHelper.cs b/ElectronNET.CLI/EmbeddedFileHelper.cs index bcaa246..aa405e3 100644 --- a/ElectronNET.CLI/EmbeddedFileHelper.cs +++ b/ElectronNET.CLI/EmbeddedFileHelper.cs @@ -19,7 +19,7 @@ namespace ElectronNET.CLI { using (var fileStream = File.Create(Path.Combine(targetPath, file))) { - var streamFromEmbeddedFile = GetTestResourceFileStream("ElectronHost." + namespacePath + file); + var streamFromEmbeddedFile = GetTestResourceFileStream(namespacePath + file); streamFromEmbeddedFile.CopyTo(fileStream); } } diff --git a/ElectronNET.CLI/ProcessHelper.cs b/ElectronNET.CLI/ProcessHelper.cs index 3263ba3..605d0c8 100644 --- a/ElectronNET.CLI/ProcessHelper.cs +++ b/ElectronNET.CLI/ProcessHelper.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Runtime.InteropServices; namespace ElectronNET.CLI { @@ -9,7 +10,18 @@ namespace ElectronNET.CLI { using (Process cmd = new Process()) { - cmd.StartInfo.FileName = "cmd.exe"; + bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + + if (isWindows) + { + cmd.StartInfo.FileName = "cmd.exe"; + } + else + { + // works for OSX and Linux (at least on Ubuntu) + cmd.StartInfo.FileName = "bash"; + } + cmd.StartInfo.RedirectStandardInput = true; cmd.StartInfo.RedirectStandardOutput = true; cmd.StartInfo.CreateNoWindow = true; diff --git a/ElectronNET.CLI/Program.cs b/ElectronNET.CLI/Program.cs index b851cdf..63caac0 100644 --- a/ElectronNET.CLI/Program.cs +++ b/ElectronNET.CLI/Program.cs @@ -4,9 +4,11 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; +using System.Xml.Linq; namespace ElectronNET.CLI { + class Program { static void Main(string[] args) @@ -28,6 +30,9 @@ namespace ElectronNET.CLI case BuildCommand.COMMAND_NAME: command = new BuildCommand(); break; + case InitCommand.COMMAND_NAME: + command = new InitCommand(); + break; case "--help": case "--h": case "help": diff --git a/ElectronNET.CLI/devCleanup.cmd b/ElectronNET.CLI/devCleanup.cmd index 611fffc..803ea4f 100644 --- a/ElectronNET.CLI/devCleanup.cmd +++ b/ElectronNET.CLI/devCleanup.cmd @@ -1,2 +1,2 @@ -rd /s /q %userprofile%\.nuget\packages\.tools\electronnet.cli -rd /s /q %userprofile%\.nuget\packages\electronnet.cli +rd /s /q %userprofile%\.nuget\packages\.tools\electronnet.cli 2>nul +rd /s /q %userprofile%\.nuget\packages\electronnet.cli 2>nul diff --git a/ElectronNET.CLI/electronnet.json b/ElectronNET.CLI/electronnet.json new file mode 100644 index 0000000..653cc60 --- /dev/null +++ b/ElectronNET.CLI/electronnet.json @@ -0,0 +1,3 @@ +{ + "executable": "{{executable}}" +} \ No newline at end of file diff --git a/ElectronNET.Host/main.js b/ElectronNET.Host/main.js index 0e766de..b189e66 100644 --- a/ElectronNET.Host/main.js +++ b/ElectronNET.Host/main.js @@ -31,19 +31,22 @@ function startSocketApiBridge(port) { function startAspCoreBackend(electronPort) { portfinder(8000, (error, electronWebPort) => { loadURL = `http://localhost:${electronWebPort}` - const params = [`/electronPort=${electronPort}`, `/electronWebPort=${electronWebPort}`]; + const parameters = [`/electronPort=${electronPort}`, `/electronWebPort=${electronWebPort}`]; - var binPath = path.join(__dirname, 'bin'); - fs.readdir(binPath, (error, files) => { - const exeFiles = files.filter((name) => name.indexOf('.exe') > -1); - const exeFileName = exeFiles[0]; - const apipath = path.join(binPath, exeFileName); - apiProcess = process(apipath, params); + const manifestFile = require("./bin/electronnet.json"); + let binaryFile = manifestFile.executable; + + const os = require("os"); + if(os.platform() === "win32") { + binaryFile = binaryFile + '.exe'; + } + + const binFilePath = path.join(__dirname, 'bin', binaryFile); + apiProcess = process(binFilePath, parameters); - apiProcess.stdout.on('data', (data) => { - var text = data.toString(); - console.log(`stdout: ${data.toString()}`); - }); + apiProcess.stdout.on('data', (data) => { + var text = data.toString(); + console.log(`stdout: ${data.toString()}`); }); }); } @@ -57,10 +60,10 @@ app.on('window-all-closed', () => { } }); -// app.on('activate', () => { -// // On macOS it's common to re-create a window in the app when the -// // dock icon is clicked and there are no other windows open. -// if (window === null) { -// createWindow(); -// } -// }); \ No newline at end of file +//app.on('activate', () => { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. +// if (win === null) { +// createWindow(); +// } +//}); \ No newline at end of file diff --git a/ElectronNET.WebApp/ElectronNET.WebApp.csproj b/ElectronNET.WebApp/ElectronNET.WebApp.csproj index afa9da2..a1ae41d 100644 --- a/ElectronNET.WebApp/ElectronNET.WebApp.csproj +++ b/ElectronNET.WebApp/ElectronNET.WebApp.csproj @@ -1,15 +1,13 @@ + - netcoreapp2.0 win10-x64 - - @@ -21,7 +19,6 @@ - @@ -34,4 +31,9 @@ PreserveNewest + + + PreserveNewest + + diff --git a/ElectronNET.WebApp/electronnet.json b/ElectronNET.WebApp/electronnet.json new file mode 100644 index 0000000..4ada330 --- /dev/null +++ b/ElectronNET.WebApp/electronnet.json @@ -0,0 +1,3 @@ +{ + "executable": "ElectronNET.WebApp" +} \ No newline at end of file diff --git a/NuGet.config b/NuGet.config index 01f8e3e..9eb1b6d 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,7 +1,9 @@ - + + + \ No newline at end of file