2018-09-19 13:10:07 -07:00
|
|
|
|
/*
|
2019-01-09 16:55:20 -08:00
|
|
|
|
Copyright (c) 2019, Lars Brubaker, John Lewin
|
2018-09-19 13:10:07 -07:00
|
|
|
|
All rights reserved.
|
|
|
|
|
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
|
|
|
|
1. Redistributions of source code must retain the above copyright notice, this
|
|
|
|
|
|
list of conditions and the following disclaimer.
|
|
|
|
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
|
|
|
|
this list of conditions and the following disclaimer in the documentation
|
|
|
|
|
|
and/or other materials provided with the distribution.
|
|
|
|
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
|
|
|
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
|
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
|
|
|
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
|
|
|
|
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
|
|
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
|
|
|
|
|
|
|
The views and conclusions contained in the software and documentation are those
|
|
|
|
|
|
of the authors and should not be interpreted as representing official policies,
|
|
|
|
|
|
either expressed or implied, of the FreeBSD Project.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
using System;
|
2017-08-20 02:34:39 -07:00
|
|
|
|
using System.Globalization;
|
|
|
|
|
|
using System.IO;
|
2018-11-27 12:22:38 -08:00
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.ServiceModel;
|
|
|
|
|
|
using System.ServiceModel.Description;
|
2017-08-20 02:34:39 -07:00
|
|
|
|
using System.Threading;
|
2017-09-24 07:49:51 -07:00
|
|
|
|
using MatterHackers.Agg.Platform;
|
2018-01-01 19:52:49 -08:00
|
|
|
|
using MatterHackers.MatterControl.DataStorage;
|
2018-11-27 12:22:38 -08:00
|
|
|
|
using MatterHackers.MatterControl.PrintQueue;
|
2019-01-09 16:55:20 -08:00
|
|
|
|
using MatterHackers.MatterControl.SettingsManagement;
|
2018-09-02 13:50:43 -07:00
|
|
|
|
using MatterHackers.MatterControl.SlicerConfiguration;
|
2018-09-19 14:51:03 -07:00
|
|
|
|
using MatterHackers.SerialPortCommunication.FrostedSerial;
|
2018-09-02 13:50:43 -07:00
|
|
|
|
using Microsoft.Extensions.Configuration;
|
2019-01-09 16:55:20 -08:00
|
|
|
|
using Mindscape.Raygun4Net;
|
2018-10-19 15:53:16 -07:00
|
|
|
|
using SQLiteWin32;
|
2017-08-20 02:34:39 -07:00
|
|
|
|
|
|
|
|
|
|
namespace MatterHackers.MatterControl
|
|
|
|
|
|
{
|
2018-09-19 13:10:07 -07:00
|
|
|
|
class Program
|
2017-08-20 02:34:39 -07:00
|
|
|
|
{
|
2018-11-27 12:22:38 -08:00
|
|
|
|
private static EventWaitHandle waitHandle;
|
|
|
|
|
|
|
2019-01-09 16:55:20 -08:00
|
|
|
|
private const int RaygunMaxNotifications = 15;
|
|
|
|
|
|
|
|
|
|
|
|
private static int raygunNotificationCount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
private static RaygunClient _raygunClient;
|
|
|
|
|
|
|
2018-11-27 12:22:38 -08:00
|
|
|
|
private static string mainServiceName = "";
|
|
|
|
|
|
|
2018-09-19 13:10:07 -07:00
|
|
|
|
[STAThread]
|
|
|
|
|
|
static void Main(string[] args)
|
2017-08-20 02:34:39 -07:00
|
|
|
|
{
|
2019-01-09 16:55:20 -08:00
|
|
|
|
// Set the global culture for the app, current thread and all new threads
|
2017-08-20 02:34:39 -07:00
|
|
|
|
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
|
2018-01-03 10:46:39 -08:00
|
|
|
|
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;
|
2019-01-09 16:55:20 -08:00
|
|
|
|
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
|
|
|
|
|
|
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
|
2017-12-16 19:25:46 -08:00
|
|
|
|
|
2018-11-29 13:41:24 -08:00
|
|
|
|
// make sure we can build a system relevant serial port
|
2018-09-19 14:51:03 -07:00
|
|
|
|
FrostedSerialPortFactory.GetPlatformSerialPort = (serialPortName) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
return new CSharpSerialPortWrapper(serialPortName);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2018-09-02 13:50:43 -07:00
|
|
|
|
// Set default Agg providers
|
2018-12-05 11:33:00 -08:00
|
|
|
|
AggContext.Config.ProviderTypes.SystemWindowProvider = "MatterHackers.MatterControl.WinformsSingleWindowProvider, MatterControl.Winforms";
|
2018-09-02 13:50:43 -07:00
|
|
|
|
|
2018-09-04 12:18:11 -07:00
|
|
|
|
string userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
|
|
|
|
|
|
|
2018-11-27 12:22:38 -08:00
|
|
|
|
//#if IS_WINDOWS
|
|
|
|
|
|
waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset, "MatterControl#Startup", out bool created);
|
|
|
|
|
|
|
|
|
|
|
|
if (!created)
|
|
|
|
|
|
{
|
|
|
|
|
|
// If an instance is already running, create a service proxy and execute ShellOpenFile
|
|
|
|
|
|
var proxy = new ServiceProxy();
|
|
|
|
|
|
|
|
|
|
|
|
// and at least one argument is an acceptable shell file extension
|
|
|
|
|
|
var itemsToAdd = args.Where(f => File.Exists(f) && shellFileExtensions.Contains(Path.GetExtension(f).ToLower()));
|
|
|
|
|
|
if (itemsToAdd.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
// notify the running instance of the event
|
|
|
|
|
|
proxy.ShellOpenFile(itemsToAdd.ToArray());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
System.Threading.Thread.Sleep(1000);
|
|
|
|
|
|
|
|
|
|
|
|
// Finally, close the process spawned by Explorer.exe
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
//#endif
|
|
|
|
|
|
|
|
|
|
|
|
var serviceHost = new ServiceHost(
|
2019-01-16 09:06:30 -08:00
|
|
|
|
typeof(LocalService),
|
2018-11-27 12:22:38 -08:00
|
|
|
|
new Uri[] { new Uri("net.pipe://localhost/") });
|
|
|
|
|
|
|
|
|
|
|
|
serviceHost.AddServiceEndpoint(typeof(IMainService), new NetNamedPipeBinding(), mainServiceName);
|
|
|
|
|
|
serviceHost.Open();
|
|
|
|
|
|
|
|
|
|
|
|
Console.Write(
|
2019-01-16 09:06:30 -08:00
|
|
|
|
"Service started: {0};",
|
2018-11-27 12:22:38 -08:00
|
|
|
|
string.Join(", ", serviceHost.Description.Endpoints.Select(s => s.ListenUri.AbsoluteUri).ToArray()));
|
2019-01-16 09:06:30 -08:00
|
|
|
|
|
2018-09-02 13:50:43 -07:00
|
|
|
|
// Load optional user configuration
|
|
|
|
|
|
IConfiguration config = new ConfigurationBuilder()
|
|
|
|
|
|
.AddJsonFile("appsettings.json", optional: true)
|
2018-09-04 12:18:11 -07:00
|
|
|
|
.AddJsonFile(Path.Combine(userProfilePath, "MatterControl.json"), optional: true)
|
2018-09-02 13:50:43 -07:00
|
|
|
|
.Build();
|
|
|
|
|
|
|
|
|
|
|
|
// Override defaults via configuration
|
|
|
|
|
|
config.Bind("Agg:ProviderTypes", AggContext.Config.ProviderTypes);
|
|
|
|
|
|
config.Bind("Agg:GraphicsMode", AggContext.Config.GraphicsMode);
|
2018-09-04 12:18:11 -07:00
|
|
|
|
|
2018-09-02 13:50:43 -07:00
|
|
|
|
Slicer.RunInProcess = config.GetValue<bool>("MatterControl:Slicer:Debug");
|
2019-01-16 09:31:49 -08:00
|
|
|
|
Application.EnableF5Collect = config.GetValue<bool>("MatterControl:Application:EnableF5Collect");
|
2017-10-12 12:16:09 -07:00
|
|
|
|
|
2017-08-20 02:34:39 -07:00
|
|
|
|
// Make sure we have the right working directory as we assume everything relative to the executable.
|
|
|
|
|
|
Directory.SetCurrentDirectory(Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location));
|
|
|
|
|
|
|
2018-10-19 15:53:16 -07:00
|
|
|
|
Datastore.Instance.Initialize(DesktopSqlite.CreateInstance());
|
2019-01-09 16:55:20 -08:00
|
|
|
|
#if !DEBUG
|
|
|
|
|
|
// Conditionally spin up error reporting if not on the Stable channel
|
|
|
|
|
|
string channel = UserSettings.Instance.get(UserSettingsKey.UpdateFeedType);
|
|
|
|
|
|
if (string.IsNullOrEmpty(channel) || channel != "release" || OemSettings.Instance.WindowTitleExtra == "Experimental")
|
|
|
|
|
|
#endif
|
|
|
|
|
|
{
|
|
|
|
|
|
System.Windows.Forms.Application.ThreadException += (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if(raygunNotificationCount++ < RaygunMaxNotifications)
|
|
|
|
|
|
{
|
|
|
|
|
|
_raygunClient.Send(e.Exception);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
AppDomain.CurrentDomain.UnhandledException += (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if (raygunNotificationCount++ < RaygunMaxNotifications)
|
|
|
|
|
|
{
|
|
|
|
|
|
_raygunClient.Send(e.ExceptionObject as Exception);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2017-08-20 02:34:39 -07:00
|
|
|
|
|
2018-08-02 17:56:59 -07:00
|
|
|
|
// Init platformFeaturesProvider before ShowAsSystemWindow
|
2018-09-05 13:21:25 -07:00
|
|
|
|
string platformFeaturesProvider = "MatterHackers.MatterControl.WindowsPlatformsFeatures, MatterControl.Winforms";
|
2018-09-19 13:10:07 -07:00
|
|
|
|
|
2018-12-15 08:53:46 -08:00
|
|
|
|
AppContext.Platform = AggContext.CreateInstanceFrom<INativePlatformFeatures>(platformFeaturesProvider);
|
|
|
|
|
|
AppContext.Platform.InitPluginFinder();
|
|
|
|
|
|
AppContext.Platform.ProcessCommandline();
|
2018-08-02 17:56:59 -07:00
|
|
|
|
|
2018-10-31 14:06:39 -07:00
|
|
|
|
config.Bind("MatterControl", MatterHackers.MatterControl.AppContext.Options);
|
|
|
|
|
|
|
2017-12-16 19:25:46 -08:00
|
|
|
|
// Get startup bounds from MatterControl and construct system window
|
|
|
|
|
|
//var systemWindow = new DesktopMainWindow(400, 200)
|
2017-12-18 17:27:28 -08:00
|
|
|
|
var (width, height) = RootSystemWindow.GetStartupBounds();
|
2017-12-16 19:25:46 -08:00
|
|
|
|
|
2017-12-20 18:25:12 -08:00
|
|
|
|
var systemWindow = Application.LoadRootWindow(width, height);
|
|
|
|
|
|
systemWindow.ShowAsSystemWindow();
|
2017-12-17 00:17:21 -08:00
|
|
|
|
}
|
2018-11-27 12:22:38 -08:00
|
|
|
|
|
|
|
|
|
|
private static string[] shellFileExtensions = new string[] { ".stl", ".amf" };
|
|
|
|
|
|
|
|
|
|
|
|
private static readonly object locker = new object();
|
|
|
|
|
|
|
|
|
|
|
|
public class LocalService : IMainService
|
|
|
|
|
|
{
|
|
|
|
|
|
public void ShellOpenFile(string[] files)
|
|
|
|
|
|
{
|
|
|
|
|
|
// If at least one argument is an acceptable shell file extension
|
2019-01-16 09:06:30 -08:00
|
|
|
|
var itemsToAdd = files.Where(f => File.Exists(f)
|
2018-11-27 12:22:38 -08:00
|
|
|
|
&& shellFileExtensions.Contains(Path.GetExtension(f).ToLower()));
|
|
|
|
|
|
|
|
|
|
|
|
if (itemsToAdd.Any())
|
|
|
|
|
|
{
|
|
|
|
|
|
lock (locker)
|
|
|
|
|
|
{
|
|
|
|
|
|
// Add each file
|
|
|
|
|
|
foreach (string file in itemsToAdd)
|
|
|
|
|
|
{
|
|
|
|
|
|
ApplicationController.Instance.ShellOpenFile(file);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class ServiceProxy : ClientBase<IMainService>
|
|
|
|
|
|
{
|
|
|
|
|
|
public ServiceProxy()
|
|
|
|
|
|
: base(
|
|
|
|
|
|
new ServiceEndpoint(
|
|
|
|
|
|
ContractDescription.GetContract(typeof(IMainService)),
|
2019-01-16 09:06:30 -08:00
|
|
|
|
new NetNamedPipeBinding(),
|
2018-11-27 12:22:38 -08:00
|
|
|
|
new EndpointAddress($"net.pipe://localhost/{mainServiceName}")))
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void ShellOpenFile(string[] files)
|
|
|
|
|
|
{
|
|
|
|
|
|
Channel.ShellOpenFile(files);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[ServiceContract]
|
|
|
|
|
|
public interface IMainService
|
|
|
|
|
|
{
|
|
|
|
|
|
[OperationContract]
|
|
|
|
|
|
void ShellOpenFile(string[] files);
|
2017-12-16 19:25:46 -08:00
|
|
|
|
}
|
2017-08-20 02:34:39 -07:00
|
|
|
|
}
|