diff --git a/Directory.Packages.props b/Directory.Packages.props index 2e1b042d8..5b65344c3 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -28,7 +28,6 @@ - diff --git a/GVFS.sln b/GVFS.sln index 80a2cbf0e..5cddccefb 100644 --- a/GVFS.sln +++ b/GVFS.sln @@ -33,8 +33,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GVFS.ReadObjectHook", "GVFS EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GVFS.Service", "GVFS\GVFS.Service\GVFS.Service.csproj", "{5E236AF3-31D7-4313-A129-F080FF058283}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GVFS.Service.UI", "GVFS\GVFS.Service.UI\GVFS.Service.UI.csproj", "{D8FB16E2-EAE0-4E05-A993-940062CD7CA7}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GVFS.Tests", "GVFS\GVFS.Tests\GVFS.Tests.csproj", "{FE70E0D6-B0A6-421D-AA12-F28F822F09A0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GVFS.UnitTests", "GVFS\GVFS.UnitTests\GVFS.UnitTests.csproj", "{1A46C414-7F39-4EF0-B216-A88033D18678}" @@ -115,10 +113,6 @@ Global {5E236AF3-31D7-4313-A129-F080FF058283}.Debug|x64.Build.0 = Debug|Any CPU {5E236AF3-31D7-4313-A129-F080FF058283}.Release|x64.ActiveCfg = Release|Any CPU {5E236AF3-31D7-4313-A129-F080FF058283}.Release|x64.Build.0 = Release|Any CPU - {D8FB16E2-EAE0-4E05-A993-940062CD7CA7}.Debug|x64.ActiveCfg = Debug|Any CPU - {D8FB16E2-EAE0-4E05-A993-940062CD7CA7}.Debug|x64.Build.0 = Debug|Any CPU - {D8FB16E2-EAE0-4E05-A993-940062CD7CA7}.Release|x64.ActiveCfg = Release|Any CPU - {D8FB16E2-EAE0-4E05-A993-940062CD7CA7}.Release|x64.Build.0 = Release|Any CPU {FE70E0D6-B0A6-421D-AA12-F28F822F09A0}.Debug|x64.ActiveCfg = Debug|Any CPU {FE70E0D6-B0A6-421D-AA12-F28F822F09A0}.Debug|x64.Build.0 = Debug|Any CPU {FE70E0D6-B0A6-421D-AA12-F28F822F09A0}.Release|x64.ActiveCfg = Release|Any CPU diff --git a/GVFS/GVFS.Common/GVFSConstants.cs b/GVFS/GVFS.Common/GVFSConstants.cs index 24374b26a..e81ecc635 100644 --- a/GVFS/GVFS.Common/GVFSConstants.cs +++ b/GVFS/GVFS.Common/GVFSConstants.cs @@ -68,7 +68,6 @@ public static class Service { public const string ServiceName = "GVFS.Service"; public const string LogDirectory = "Logs"; - public const string UIName = "GVFS.Service.UI"; } public static class MediaTypes @@ -108,7 +107,6 @@ public static class LogFileTypes public const string Prefetch = "prefetch"; public const string Repair = "repair"; public const string Service = "service"; - public const string ServiceUI = "service_ui"; public const string Sparse = "sparse"; public const string UpgradeVerb = UpgradePrefix + "_verb"; public const string UpgradeProcess = UpgradePrefix + "_process"; diff --git a/GVFS/GVFS.Installers/Setup.iss b/GVFS/GVFS.Installers/Setup.iss index 886da1042..f8a166d75 100644 --- a/GVFS/GVFS.Installers/Setup.iss +++ b/GVFS/GVFS.Installers/Setup.iss @@ -15,7 +15,6 @@ #define GVFSConfigFileName "gvfs.config" #define GVFSStatuscacheTokenFileName "EnableGitStatusCacheToken.dat" #define ServiceName "GVFS.Service" -#define ServiceUIName "VFS For Git" [Setup] AppId={{489CA581-F131-4C28-BE04-4FB178933E6D} @@ -66,9 +65,6 @@ DestDir: "{app}"; Flags: ignoreversion; Source:"{#LayoutDir}\GVFS.Service.exe"; [Dirs] Name: "{app}\ProgramData\{#ServiceName}"; Permissions: users-readexec -[Icons] -Name: "{commonstartmenu}\{#ServiceUIName}"; Filename: "{app}\GVFS.Service.UI.exe"; AppUserModelID: "GVFS" - [UninstallDelete] ; Deletes the entire installation directory, including files and subdirectories Type: filesandordirs; Name: "{app}"; @@ -249,38 +245,6 @@ begin end; end; -procedure StartGVFSServiceUI(); -var - ResultCode: integer; -begin - if GetEnv('GVFS_UNATTENDED') = '1' then - begin - Log('StartGVFSServiceUI: Skipping launching GVFS.Service.UI'); - end - else if ExecAsOriginalUser(ExpandConstant('{app}\GVFS.Service.UI.exe'), '', '', SW_HIDE, ewNoWait, ResultCode) then - begin - Log('StartGVFSServiceUI: Successfully launched GVFS.Service.UI'); - end - else - begin - Log('StartGVFSServiceUI: Failed to launch GVFS.Service.UI'); - end; -end; - -procedure StopGVFSServiceUI(); -var - ResultCode: integer; -begin - if Exec('powershell.exe', '-NoProfile "Stop-Process -Name GVFS.Service.UI"', '', SW_HIDE, ewNoWait, ResultCode) then - begin - Log('StopGVFSServiceUI: Successfully stopped GVFS.Service.UI'); - end - else - begin - RaiseException('Fatal: Could not stop process: GVFS.Service.UI'); - end; -end; - function DeleteFileIfItExists(FilePath: string) : Boolean; begin Result := False; @@ -688,7 +652,6 @@ begin ssPostInstall: begin MigrateConfigAndStatusCacheFiles(); - StartGVFSServiceUI(); if ExpandConstant('{param:REMOUNTREPOS|true}') = 'true' then begin MountRepos(); @@ -707,7 +670,6 @@ begin case CurStep of usUninstall: begin - StopGVFSServiceUI(); UninstallService('GVFS.Service', False); RemovePath(ExpandConstant('{app}')); end; @@ -731,7 +693,6 @@ begin Abort(); end; StopService('GVFS.Service'); - StopGVFSServiceUI(); UninstallGvFlt(); UninstallProjFSIfNecessary(); end; diff --git a/GVFS/GVFS.Payload/GVFS.Payload.csproj b/GVFS/GVFS.Payload/GVFS.Payload.csproj index e7bc79415..830581714 100644 --- a/GVFS/GVFS.Payload/GVFS.Payload.csproj +++ b/GVFS/GVFS.Payload/GVFS.Payload.csproj @@ -22,7 +22,6 @@ - @@ -48,7 +47,6 @@ $(OutputPath)\GVFS.PostIndexChangedHook.exe; $(OutputPath)\GVFS.ReadObjectHook.exe; $(OutputPath)\GVFS.Service.exe; - $(OutputPath)\GVFS.Service.UI.exe; $(OutputPath)\GVFS.VirtualFileSystemHook.exe; $(OutputPath)\GVFS.Virtualization.dll;"> Microsoft400 diff --git a/GVFS/GVFS.Payload/layout.bat b/GVFS/GVFS.Payload/layout.bat index ebdae19c2..70a8de57b 100644 --- a/GVFS/GVFS.Payload/layout.bat +++ b/GVFS/GVFS.Payload/layout.bat @@ -54,7 +54,6 @@ xcopy /Y /S %BUILD_OUT%\GVFS\%MANAGED_OUT_FRAGMENT%\* %OUTPUT% xcopy /Y /S %BUILD_OUT%\GVFS.Hooks\%MANAGED_OUT_FRAGMENT%\* %OUTPUT% xcopy /Y /S %BUILD_OUT%\GVFS.Mount\%MANAGED_OUT_FRAGMENT%\* %OUTPUT% xcopy /Y /S %BUILD_OUT%\GVFS.Service\%MANAGED_OUT_FRAGMENT%\* %OUTPUT% -xcopy /Y /S %BUILD_OUT%\GVFS.Service.UI\%MANAGED_OUT_FRAGMENT%\* %OUTPUT% xcopy /Y /S %BUILD_OUT%\GitHooksLoader\%NATIVE_OUT_FRAGMENT%\* %OUTPUT% xcopy /Y /S %BUILD_OUT%\GVFS.PostIndexChangedHook\%NATIVE_OUT_FRAGMENT%\* %OUTPUT% xcopy /Y /S %BUILD_OUT%\GVFS.ReadObjectHook\%NATIVE_OUT_FRAGMENT%\* %OUTPUT% diff --git a/GVFS/GVFS.Service.UI/Data/ActionItem.cs b/GVFS/GVFS.Service.UI/Data/ActionItem.cs deleted file mode 100644 index 1034ea0aa..000000000 --- a/GVFS/GVFS.Service.UI/Data/ActionItem.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Xml.Serialization; - -namespace GVFS.Service.UI.Data -{ - [XmlRoot("action")] - public class ActionItem - { - [XmlAttribute("content")] - public string Content { get; set; } - - [XmlAttribute("arguments")] - public string Arguments { get; set; } - - [XmlAttribute("activationtype")] - public string ActivationType { get; set; } - } -} \ No newline at end of file diff --git a/GVFS/GVFS.Service.UI/Data/ActionsData.cs b/GVFS/GVFS.Service.UI/Data/ActionsData.cs deleted file mode 100644 index 56b92af81..000000000 --- a/GVFS/GVFS.Service.UI/Data/ActionsData.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Xml.Serialization; - -namespace GVFS.Service.UI.Data -{ - public class ActionsData - { - [XmlAnyElement("actions")] - public XmlList Actions { get; set; } - } -} diff --git a/GVFS/GVFS.Service.UI/Data/BindingData.cs b/GVFS/GVFS.Service.UI/Data/BindingData.cs deleted file mode 100644 index b364abed5..000000000 --- a/GVFS/GVFS.Service.UI/Data/BindingData.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Xml.Serialization; - -namespace GVFS.Service.UI.Data -{ - public class BindingData - { - [XmlAttribute("template")] - public string Template { get; set; } - - [XmlAnyElement] - public XmlList Items { get; set; } - } -} diff --git a/GVFS/GVFS.Service.UI/Data/BindingItem.cs b/GVFS/GVFS.Service.UI/Data/BindingItem.cs deleted file mode 100644 index e116d1a16..000000000 --- a/GVFS/GVFS.Service.UI/Data/BindingItem.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Xml.Serialization; - -namespace GVFS.Service.UI.Data -{ - public abstract class BindingItem - { - [XmlRoot("text")] - public class TextData : BindingItem - { - public TextData() - { - // Required for serialization - } - - public TextData(string value) - { - this.Value = value; - } - - [XmlText] - public string Value { get; set; } - } - - [XmlRoot("image")] - public class ImageData : BindingItem - { - [XmlAttribute("placement")] - public string Placement { get; set; } - - [XmlAttribute("src")] - public string Source { get; set; } - - [XmlAttribute("hint-crop")] - public string HintCrop { get; set; } - } - } -} diff --git a/GVFS/GVFS.Service.UI/Data/ToastData.cs b/GVFS/GVFS.Service.UI/Data/ToastData.cs deleted file mode 100644 index 6750e4e78..000000000 --- a/GVFS/GVFS.Service.UI/Data/ToastData.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Xml.Serialization; - -namespace GVFS.Service.UI.Data -{ - [XmlRoot("toast")] - public class ToastData - { - [XmlAttribute("launch")] - public string Launch { get; set; } - - [XmlElement("visual")] - public VisualData Visual { get; set; } - - [XmlElement("actions")] - public ActionsData Actions { get; set; } - - [XmlElement("scenario")] - public string Scenario { get; set; } - } -} diff --git a/GVFS/GVFS.Service.UI/Data/VisualData.cs b/GVFS/GVFS.Service.UI/Data/VisualData.cs deleted file mode 100644 index 10fb75d49..000000000 --- a/GVFS/GVFS.Service.UI/Data/VisualData.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Xml.Serialization; - -namespace GVFS.Service.UI.Data -{ - public class VisualData - { - [XmlElement("binding")] - public BindingData Binding { get; set; } - } -} diff --git a/GVFS/GVFS.Service.UI/GVFS.Service.UI.csproj b/GVFS/GVFS.Service.UI/GVFS.Service.UI.csproj deleted file mode 100644 index 4f3c5ac83..000000000 --- a/GVFS/GVFS.Service.UI/GVFS.Service.UI.csproj +++ /dev/null @@ -1,22 +0,0 @@ - - - - Exe - net471 - - - - - - - - - - - - - PreserveNewest - - - - diff --git a/GVFS/GVFS.Service.UI/GVFSServiceUI.cs b/GVFS/GVFS.Service.UI/GVFSServiceUI.cs deleted file mode 100644 index c81e80b7d..000000000 --- a/GVFS/GVFS.Service.UI/GVFSServiceUI.cs +++ /dev/null @@ -1,56 +0,0 @@ -using GVFS.Common; -using GVFS.Common.NamedPipes; -using GVFS.Common.Tracing; -using System; -using System.Threading; - -namespace GVFS.Service.UI -{ - public class GVFSServiceUI - { - private readonly ITracer tracer; - private readonly GVFSToastRequestHandler toastRequestHandler; - - public GVFSServiceUI(ITracer tracer, GVFSToastRequestHandler toastRequestHandler) - { - this.tracer = tracer; - this.toastRequestHandler = toastRequestHandler; - } - - public void Start(string[] args) - { - using (ITracer activity = this.tracer.StartActivity("Start", EventLevel.Informational)) - using (NamedPipeServer server = NamedPipeServer.StartNewServer(GVFSConstants.Service.UIName, this.tracer, this.HandleRequest)) - { - ManualResetEvent mre = new ManualResetEvent(false); - mre.WaitOne(); - } - } - - private void HandleRequest(ITracer tracer, string request, NamedPipeServer.Connection connection) - { - try - { - NamedPipeMessages.Message message = NamedPipeMessages.Message.FromString(request); - switch (message.Header) - { - case NamedPipeMessages.Notification.Request.Header: - NamedPipeMessages.Notification.Request toastRequest = NamedPipeMessages.Notification.Request.FromMessage(message); - if (toastRequest != null) - { - using (ITracer activity = this.tracer.StartActivity("SendToast", EventLevel.Informational)) - { - this.toastRequestHandler.HandleToastRequest(activity, toastRequest); - } - } - - break; - } - } - catch (Exception e) - { - this.tracer.RelatedError("Unhandled exception: {0}", e.ToString()); - } - } - } -} diff --git a/GVFS/GVFS.Service.UI/GVFSToastRequestHandler.cs b/GVFS/GVFS.Service.UI/GVFSToastRequestHandler.cs deleted file mode 100644 index f6c5872b8..000000000 --- a/GVFS/GVFS.Service.UI/GVFSToastRequestHandler.cs +++ /dev/null @@ -1,193 +0,0 @@ -using GVFS.Common.NamedPipes; -using GVFS.Common.Tracing; -using System; -using System.Diagnostics; -using System.IO; - -namespace GVFS.Service.UI -{ - public class GVFSToastRequestHandler - { - private const string VFSForGitAutomountStartTitle= "VFS For Git Automount"; - private const string VFSForGitAutomountStartMessageFormat = "Attempting to mount {0} VFS For Git {1}"; - private const string VFSForGitMultipleRepos = "repos"; - private const string VFSForGitSingleRepo = "repo"; - - private const string VFSForGitAutomountSuccessTitle = "VFS For Git Automount"; - private const string VFSForGitAutomountSuccessMessageFormat = "The following VFS For Git repo is now mounted: {0}{1}"; - - private const string VFSForGitAutomountErrorTitle = "VFS For Git Automount"; - private const string VFSForGitAutomountErrorMessageFormat = "The following VFS For Git repo failed to mount: {0}{1}"; - private const string VFSForGitAutomountButtonTitle = "Retry"; - - private const string VFSForGitUpgradeTitleFormat = "New version {0} is available"; - private const string VFSForGitUpgradeMessage = "Upgrade will unmount and remount VFS For Git repos, ensure you are at a stopping point. When ready, click Upgrade button to run upgrade."; - private const string VFSForGitUpgradeButtonTitle = "Upgrade"; - - private const string VFSForGitRemountActionPrefix = "gvfs mount"; - private const string VFSForGitUpgradeActionPrefix = "gvfs upgrade --confirm"; - - private readonly ITracer tracer; - private readonly IToastNotifier toastNotifier; - - public GVFSToastRequestHandler(IToastNotifier toastNotifier, ITracer tracer) - { - this.toastNotifier = toastNotifier; - this.toastNotifier.UserResponseCallback = this.UserResponseCallback; - this.tracer = tracer; - } - - public void HandleToastRequest(ITracer tracer, NamedPipeMessages.Notification.Request request) - { - string title = null; - string message = null; - string buttonTitle = null; - string args = null; - string path = null; - - switch (request.Id) - { - case NamedPipeMessages.Notification.Request.Identifier.AutomountStart: - string reposSuffix = request.EnlistmentCount <= 1 ? VFSForGitSingleRepo : VFSForGitMultipleRepos; - title = VFSForGitAutomountStartTitle; - message = string.Format(VFSForGitAutomountStartMessageFormat, request.EnlistmentCount, reposSuffix); - break; - - case NamedPipeMessages.Notification.Request.Identifier.MountSuccess: - if (this.TryValidatePath(request.Enlistment, out path, this.tracer)) - { - title = VFSForGitAutomountSuccessTitle; - message = string.Format(VFSForGitAutomountSuccessMessageFormat, Environment.NewLine, path); - } - - break; - - case NamedPipeMessages.Notification.Request.Identifier.MountFailure: - if (this.TryValidatePath(request.Enlistment, out path, this.tracer)) - { - title = VFSForGitAutomountErrorTitle; - message = string.Format(VFSForGitAutomountErrorMessageFormat, Environment.NewLine, path); - buttonTitle = VFSForGitAutomountButtonTitle; - args = $"{VFSForGitRemountActionPrefix} {path}"; - } - - break; - - case NamedPipeMessages.Notification.Request.Identifier.UpgradeAvailable: - title = string.Format(VFSForGitUpgradeTitleFormat, request.NewVersion); - message = string.Format(VFSForGitUpgradeMessage); - buttonTitle = VFSForGitUpgradeButtonTitle; - args = $"{VFSForGitUpgradeActionPrefix}"; - break; - } - - if (title != null && message != null) - { - this.toastNotifier.Notify(title, message, buttonTitle, args); - } - } - - public void UserResponseCallback(string args) - { - if (string.IsNullOrEmpty(args)) - { - this.tracer.RelatedError($"{nameof(this.UserResponseCallback)}: Received null arguments in Toaster callback."); - return; - } - - using (ITracer activity = this.tracer.StartActivity("GVFSToastCallback", EventLevel.Informational)) - { - string gvfsCmd = null; - bool elevate = false; - - if (args.StartsWith(VFSForGitUpgradeActionPrefix)) - { - this.tracer.RelatedInfo($"gvfs upgrade action."); - gvfsCmd = "gvfs upgrade --confirm"; - elevate = true; - } - else if (args.StartsWith(VFSForGitRemountActionPrefix)) - { - string path = args.Substring(VFSForGitRemountActionPrefix.Length, args.Length - VFSForGitRemountActionPrefix.Length); - if (this.TryValidatePath(path, out string enlistment, activity)) - { - this.tracer.RelatedInfo($"gvfs mount action {enlistment}."); - gvfsCmd = $"gvfs mount \"{enlistment}\""; - } - else - { - EventMetadata metadata = new EventMetadata(); - metadata.Add(nameof(args), args); - metadata.Add(nameof(path), path); - this.tracer.RelatedError(metadata, $"{nameof(this.UserResponseCallback)}- Invalid enlistment path specified in Toaster callback."); - } - } - else - { - this.tracer.RelatedError($"{nameof(this.UserResponseCallback)}- Unknown action({args}) specified in Toaster callback."); - } - - if (!string.IsNullOrEmpty(gvfsCmd)) - { - this.launchGVFSInCommandPrompt(gvfsCmd, elevate, activity); - } - } - } - - private bool TryValidatePath(string path, out string validatedPath, ITracer tracer) - { - try - { - validatedPath = Path.GetFullPath(path); - return true; - } - catch (Exception ex) - { - EventMetadata metadata = new EventMetadata(); - metadata.Add("Exception", ex.ToString()); - metadata.Add("Path", path); - - tracer.RelatedError(metadata, $"{nameof(this.TryValidatePath)}: {path}. {ex.ToString()}"); - } - - validatedPath = null; - return false; - } - - private void launchGVFSInCommandPrompt(string fullGvfsCmd, bool elevate, ITracer tracer) - { - const string cmdPath = "CMD.exe"; - ProcessStartInfo processInfo = new ProcessStartInfo(cmdPath); - processInfo.UseShellExecute = true; - processInfo.RedirectStandardInput = false; - processInfo.RedirectStandardOutput = false; - processInfo.RedirectStandardError = false; - processInfo.WindowStyle = ProcessWindowStyle.Normal; - processInfo.CreateNoWindow = false; - - // /K option is so the user gets the time to read the output of the command and - // manually close the cmd window after that. - processInfo.Arguments = "/K " + fullGvfsCmd; - if (elevate) - { - processInfo.Verb = "runas"; - } - - tracer.RelatedInfo($"{nameof(this.UserResponseCallback)}- Running {cmdPath} /K {fullGvfsCmd}"); - - try - { - Process.Start(processInfo); - } - catch (Exception ex) - { - EventMetadata metadata = new EventMetadata(); - metadata.Add("Exception", ex.ToString()); - metadata.Add(nameof(fullGvfsCmd), fullGvfsCmd); - metadata.Add(nameof(elevate), elevate); - - tracer.RelatedError(metadata, $"{nameof(this.launchGVFSInCommandPrompt)}: Error launching {fullGvfsCmd}. {ex.ToString()}"); - } - } - } -} diff --git a/GVFS/GVFS.Service.UI/IToastNotifier.cs b/GVFS/GVFS.Service.UI/IToastNotifier.cs deleted file mode 100644 index 60cd2f15b..000000000 --- a/GVFS/GVFS.Service.UI/IToastNotifier.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; - -namespace GVFS.Service.UI -{ - public interface IToastNotifier - { - Action UserResponseCallback { get; set; } - void Notify(string title, string message, string actionButtonTitle, string callbackArgs); - } -} diff --git a/GVFS/GVFS.Service.UI/Program.cs b/GVFS/GVFS.Service.UI/Program.cs deleted file mode 100644 index 3c03bbc66..000000000 --- a/GVFS/GVFS.Service.UI/Program.cs +++ /dev/null @@ -1,46 +0,0 @@ -using GVFS.Common; -using GVFS.Common.Tracing; -using GVFS.PlatformLoader; -using System; - -namespace GVFS.Service.UI -{ - public static class Program - { - public static void Main(string[] args) - { - GVFSPlatformLoader.Initialize(); - - using (JsonTracer tracer = new JsonTracer("Microsoft.Git.GVFS.Service.UI", "Service.UI")) - { - string error; - string serviceUILogDirectory = GVFSPlatform.Instance.GetLogsDirectoryForGVFSComponent(GVFSConstants.Service.UIName); - if (!GVFSPlatform.Instance.FileSystem.TryCreateDirectoryWithAdminAndUserModifyPermissions(serviceUILogDirectory, out error)) - { - EventMetadata metadata = new EventMetadata(); - metadata.Add(nameof(serviceUILogDirectory), serviceUILogDirectory); - metadata.Add(nameof(error), error); - tracer.RelatedWarning( - metadata, - "Failed to create service UI logs directory", - Keywords.Telemetry); - } - else - { - string logFilePath = GVFSEnlistment.GetNewGVFSLogFileName( - serviceUILogDirectory, - GVFSConstants.LogFileTypes.ServiceUI, - logId: Environment.UserName); - - tracer.AddLogFileEventListener(logFilePath, EventLevel.Informational, Keywords.Any); - } - - WinToastNotifier winToastNotifier = new WinToastNotifier(tracer); - GVFSToastRequestHandler toastRequestHandler = new GVFSToastRequestHandler(winToastNotifier, tracer); - GVFSServiceUI process = new GVFSServiceUI(tracer, toastRequestHandler); - - process.Start(args); - } - } - } -} \ No newline at end of file diff --git a/GVFS/GVFS.Service.UI/WinToastNotifier.cs b/GVFS/GVFS.Service.UI/WinToastNotifier.cs deleted file mode 100644 index 8cf364dfa..000000000 --- a/GVFS/GVFS.Service.UI/WinToastNotifier.cs +++ /dev/null @@ -1,103 +0,0 @@ -using GVFS.Common; -using GVFS.Common.Tracing; -using GVFS.Service.UI.Data; -using System; -using System.IO; -using System.Xml; -using System.Xml.Serialization; -using Windows.UI.Notifications; -using XmlDocument = Windows.Data.Xml.Dom.XmlDocument; - -namespace GVFS.Service.UI -{ - public class WinToastNotifier : IToastNotifier - { - private const string ServiceAppId = "GVFS"; - private const string GVFSIconName = "GitVirtualFileSystem.ico"; - private ITracer tracer; - - public WinToastNotifier(ITracer tracer) - { - this.tracer = tracer; - } - - public Action UserResponseCallback { get; set; } - - public void Notify(string title, string message, string actionButtonTitle, string callbackArgs) - { - // Reference: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts - ToastData toastData = new ToastData(); - - toastData.Visual = new VisualData(); - - BindingData binding = new BindingData(); - toastData.Visual.Binding = binding; - - // ToastGeneric- Our toast contains VFSForGit icon and text - binding.Template = "ToastGeneric"; - binding.Items = new XmlList(); - binding.Items.Add(new BindingItem.TextData(title)); - binding.Items.Add(new BindingItem.TextData(message)); - - string logo = "file:///" + Path.Combine(ProcessHelper.GetCurrentProcessLocation(), GVFSIconName); - binding.Items.Add(new BindingItem.ImageData() - { - Source = logo, - Placement = "appLogoOverride", - HintCrop = "circle" - }); - - if (!string.IsNullOrEmpty(actionButtonTitle)) - { - ActionsData actionsData = new ActionsData(); - actionsData.Actions = new XmlList(); - actionsData.Actions.Add(new ActionItem() - { - Content = actionButtonTitle, - Arguments = string.IsNullOrEmpty(callbackArgs) ? string.Empty : callbackArgs, - ActivationType = "background" - }); - - toastData.Actions = actionsData; - } - - XmlDocument toastXml = new XmlDocument(); - using (StringWriter stringWriter = new StringWriter()) - using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { OmitXmlDeclaration = true })) - { - XmlSerializer serializer = new XmlSerializer(toastData.GetType()); - XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces(); - namespaces.Add(string.Empty, string.Empty); - - serializer.Serialize(xmlWriter, toastData, namespaces); - - toastXml.LoadXml(stringWriter.ToString()); - } - - ToastNotification toastNotification = new ToastNotification(toastXml); - toastNotification.Activated += this.ToastActivated; - toastNotification.Dismissed += this.ToastDismissed; - toastNotification.Failed += this.ToastFailed; - - ToastNotifier toastNotifier = ToastNotificationManager.CreateToastNotifier(ServiceAppId); - toastNotifier.Show(toastNotification); - } - - private void ToastActivated(ToastNotification sender, object e) - { - ToastActivatedEventArgs args = (ToastActivatedEventArgs)e; - - this.UserResponseCallback?.Invoke(args.Arguments); - } - - private void ToastDismissed(ToastNotification sender, ToastDismissedEventArgs e) - { - this.tracer.RelatedInfo($"{nameof(this.ToastDismissed)}: {e.Reason}"); - } - - private void ToastFailed(ToastNotification sender, ToastFailedEventArgs e) - { - this.tracer.RelatedInfo($"{nameof(this.ToastFailed)}: {e.ErrorCode.ToString()}"); - } - } -} diff --git a/GVFS/GVFS.Service.UI/XmlList.cs b/GVFS/GVFS.Service.UI/XmlList.cs deleted file mode 100644 index 06a2dad50..000000000 --- a/GVFS/GVFS.Service.UI/XmlList.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Xml; -using System.Xml.Schema; -using System.Xml.Serialization; - -namespace GVFS.Service.UI -{ - public class XmlList : List, IXmlSerializable where T : class - { - public XmlSchema GetSchema() - { - throw new NotImplementedException(); - } - - public void ReadXml(XmlReader reader) - { - throw new NotImplementedException(); - } - - public void WriteXml(XmlWriter writer) - { - XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); - ns.Add(string.Empty, string.Empty); - foreach (T item in this) - { - XmlSerializer xml = new XmlSerializer(item.GetType()); - xml.Serialize(writer, item, ns); - } - } - } -} diff --git a/GVFS/GVFS.Service/Configuration.cs b/GVFS/GVFS.Service/Configuration.cs index f5c8b65be..0e4ebe18e 100644 --- a/GVFS/GVFS.Service/Configuration.cs +++ b/GVFS/GVFS.Service/Configuration.cs @@ -11,7 +11,6 @@ public class Configuration private Configuration() { this.GVFSLocation = Path.Combine(AssemblyPath, GVFSPlatform.Instance.Constants.GVFSExecutableName); - this.GVFSServiceUILocation = Path.Combine(AssemblyPath, GVFSConstants.Service.UIName + GVFSPlatform.Instance.Constants.ExecutableExtension); } public static Configuration Instance @@ -36,6 +35,5 @@ public static string AssemblyPath } public string GVFSLocation { get; private set; } - public string GVFSServiceUILocation { get; private set; } } } diff --git a/GVFS/GVFS.Service/GVFS.Service.csproj b/GVFS/GVFS.Service/GVFS.Service.csproj index b557e3a41..cc8c4c9f8 100644 --- a/GVFS/GVFS.Service/GVFS.Service.csproj +++ b/GVFS/GVFS.Service/GVFS.Service.csproj @@ -8,7 +8,6 @@ - diff --git a/GVFS/GVFS.Service/GVFSService.Windows.cs b/GVFS/GVFS.Service/GVFSService.Windows.cs index 5b3048b74..f0eee8385 100644 --- a/GVFS/GVFS.Service/GVFSService.Windows.cs +++ b/GVFS/GVFS.Service/GVFSService.Windows.cs @@ -5,10 +5,8 @@ using GVFS.Platform.Windows; using GVFS.Service.Handlers; using System; -using System.Diagnostics; using System.IO; using System.Linq; -using System.Runtime.Serialization; using System.Security.AccessControl; using System.ServiceProcess; using System.Threading; @@ -130,8 +128,6 @@ protected override void OnSessionChange(SessionChangeDescription changeDescripti { this.tracer.RelatedInfo("SessionLogon detected, sessionId: {0}", changeDescription.SessionId); - this.LaunchServiceUIIfNotRunning(changeDescription.SessionId); - using (ITracer activity = this.tracer.StartActivity("LogonAutomount", EventLevel.Informational)) { this.repoRegistry.AutoMountRepos( @@ -358,9 +354,6 @@ private void CreateAndConfigureProgramDataDirectories() // Ensure the ACLs are set correctly on any files or directories that were already created (e.g. after upgrading VFS4G) Directory.SetAccessControl(serviceDataRootPath, serviceDataRootSecurity); - - // Special rules for the Service.UI logs, as non-elevated users need to be be able to write - this.CreateAndConfigureLogDirectory(GVFSPlatform.Instance.GetLogsDirectoryForGVFSComponent(GVFSConstants.Service.UIName)); } private void CreateAndConfigureLogDirectory(string path) @@ -404,50 +397,5 @@ private DirectorySecurity GetServiceDirectorySecurity(string serviceDataRootPath return serviceDataRootSecurity; } - private void LaunchServiceUIIfNotRunning(int sessionId) - { - NamedPipeClient client; - using (client = new NamedPipeClient(GVFSConstants.Service.UIName)) - { - if (!client.Connect()) - { - this.tracer.RelatedError($"Could not connect with {GVFSConstants.Service.UIName}. Attempting to relaunch."); - - this.TerminateExistingProcess(GVFSConstants.Service.UIName, sessionId); - - CurrentUser currentUser = new CurrentUser(this.tracer, sessionId); - if (!currentUser.RunAs( - Configuration.Instance.GVFSServiceUILocation, - string.Empty)) - { - this.tracer.RelatedError("Could not start " + GVFSConstants.Service.UIName); - } - else - { - this.tracer.RelatedInfo($"Successfully launched {GVFSConstants.Service.UIName}. "); - } - } - } - } - - private void TerminateExistingProcess(string processName, int sessionId) - { - try - { - foreach (Process process in Process.GetProcessesByName(processName)) - { - if (process.SessionId == sessionId) - { - this.tracer.RelatedInfo($"{nameof(this.TerminateExistingProcess)}- Stopping {processName}, in session {sessionId}."); - - process.Kill(); - } - } - } - catch (Exception ex) - { - this.tracer.RelatedError("Could not find and kill existing instances of {0}: {1}", processName, ex.Message); - } - } } } diff --git a/GVFS/GVFS.Service/Handlers/NotificationHandler.cs b/GVFS/GVFS.Service/Handlers/NotificationHandler.cs index a7777b8fc..a0ec6876c 100644 --- a/GVFS/GVFS.Service/Handlers/NotificationHandler.cs +++ b/GVFS/GVFS.Service/Handlers/NotificationHandler.cs @@ -1,47 +1,16 @@ -using GVFS.Common; -using GVFS.Common.NamedPipes; +using GVFS.Common.NamedPipes; using GVFS.Common.Tracing; -using GVFS.Platform.Windows; -using System; -using System.Diagnostics; namespace GVFS.Service.Handlers { public class NotificationHandler : INotificationHandler { - private ITracer tracer; - public NotificationHandler(ITracer tracer) { - this.tracer = tracer; } public void SendNotification(NamedPipeMessages.Notification.Request request) { - using (NamedPipeClient client = new NamedPipeClient(GVFSConstants.Service.UIName)) - { - if (client.Connect()) - { - try - { - if (!client.TrySendRequest(request.ToMessage())) - { - this.tracer.RelatedInfo("Failed to send notification request to " + GVFSConstants.Service.UIName); - } - } - catch (Exception ex) - { - EventMetadata metadata = new EventMetadata(); - metadata.Add("Exception", ex.ToString()); - metadata.Add("Identifier", request.Id); - this.tracer.RelatedError(metadata, $"{nameof(this.SendNotification)}- Could not send notification request({request.Id}. {ex.ToString()}"); - } - } - else - { - this.tracer.RelatedError($"{nameof(this.SendNotification)}- Could not connect with GVFS.Service.UI, failed to send notification request({request.Id}."); - } - } } } } diff --git a/GVFS/GVFS.UnitTests/GVFS.UnitTests.csproj b/GVFS/GVFS.UnitTests/GVFS.UnitTests.csproj index 6111e7220..efb890af3 100644 --- a/GVFS/GVFS.UnitTests/GVFS.UnitTests.csproj +++ b/GVFS/GVFS.UnitTests/GVFS.UnitTests.csproj @@ -8,7 +8,6 @@ - diff --git a/GVFS/GVFS.UnitTests/Windows/ServiceUI/GVFSToastRequestHandlerTests.cs b/GVFS/GVFS.UnitTests/Windows/ServiceUI/GVFSToastRequestHandlerTests.cs deleted file mode 100644 index 34e7073e9..000000000 --- a/GVFS/GVFS.UnitTests/Windows/ServiceUI/GVFSToastRequestHandlerTests.cs +++ /dev/null @@ -1,111 +0,0 @@ -using GVFS.Common.NamedPipes; -using GVFS.Service.UI; -using GVFS.UnitTests.Mock.Common; -using Moq; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace GVFS.UnitTests.Windows.ServiceUI -{ - [TestFixture] - public class GVFSToastRequestHandlerTests - { - private NamedPipeMessages.Notification.Request request; - private GVFSToastRequestHandler toastHandler; - private Mock mockToastNotifier; - private MockTracer tracer; - - [SetUp] - public void Setup() - { - this.tracer = new MockTracer(); - this.mockToastNotifier = new Mock(MockBehavior.Strict); - this.mockToastNotifier.SetupSet(toastNotifier => toastNotifier.UserResponseCallback = It.IsAny>()).Verifiable(); - this.toastHandler = new GVFSToastRequestHandler(this.mockToastNotifier.Object, this.tracer); - this.request = new NamedPipeMessages.Notification.Request(); - } - - [TestCase] - public void UpgradeToastIsActionableAndContainsVersionInfo() - { - const string version = "1.0.956749.2"; - - this.request.Id = NamedPipeMessages.Notification.Request.Identifier.UpgradeAvailable; - this.request.NewVersion = version; - - this.VerifyToastMessage( - expectedTitle: "New version " + version + " is available", - expectedMessage: "click Upgrade button", - expectedButtonTitle: "Upgrade", - expectedGVFSCmd: "gvfs upgrade --confirm"); - } - - [TestCase] - public void MountFailureToastIsActionableAndContainEnlistmentInfo() - { - const string enlistmentRoot = "D:\\Work\\OS"; - - this.request.Id = NamedPipeMessages.Notification.Request.Identifier.MountFailure; - this.request.Enlistment = enlistmentRoot; - - this.VerifyToastMessage( - expectedTitle: "VFS For Git Automount", - expectedMessage: enlistmentRoot, - expectedButtonTitle: "Retry", - expectedGVFSCmd: "gvfs mount " + enlistmentRoot); - } - - [TestCase] - public void MountStartIsNotActionableAndContainsEnlistmentCount() - { - const int enlistmentCount = 10; - - this.request.Id = NamedPipeMessages.Notification.Request.Identifier.AutomountStart; - this.request.EnlistmentCount = enlistmentCount; - - this.VerifyToastMessage( - expectedTitle: "VFS For Git Automount", - expectedMessage: "mount " + enlistmentCount.ToString() + " VFS For Git repos", - expectedButtonTitle: null, - expectedGVFSCmd: null); - } - - [TestCase] - public void UnknownToastRequestGetsIgnored() - { - this.request.Id = (NamedPipeMessages.Notification.Request.Identifier)10; - this.request.EnlistmentCount = 232; - this.request.Enlistment = "C:\\OS"; - - this.toastHandler.HandleToastRequest(this.tracer, this.request); - - this.mockToastNotifier.Verify( - toastNotifier => toastNotifier.Notify( - It.IsAny(), - It.IsAny(), - It.IsAny(), - It.IsAny()), - Times.Never()); - } - - private void VerifyToastMessage( - string expectedTitle, - string expectedMessage, - string expectedButtonTitle, - string expectedGVFSCmd) - { - this.mockToastNotifier.Setup(toastNotifier => toastNotifier.Notify( - expectedTitle, - It.Is(message => message.Contains(expectedMessage)), - expectedButtonTitle, - expectedGVFSCmd)); - - this.toastHandler.HandleToastRequest(this.tracer, this.request); - this.mockToastNotifier.VerifyAll(); - } - } -} diff --git a/GVFS/GVFS/CommandLine/DiagnoseVerb.cs b/GVFS/GVFS/CommandLine/DiagnoseVerb.cs index 1d3a71639..3840bbbb4 100644 --- a/GVFS/GVFS/CommandLine/DiagnoseVerb.cs +++ b/GVFS/GVFS/CommandLine/DiagnoseVerb.cs @@ -133,13 +133,6 @@ protected override void Execute(GVFSEnlistment enlistment) this.ServiceName, copySubFolders: true); - // service ui - this.CopyAllFiles( - GVFSPlatform.Instance.GetCommonAppDataRootForGVFS(), - archiveFolderPath, - GVFSConstants.Service.UIName, - copySubFolders: true); - if (GVFSPlatform.Instance.UnderConstruction.SupportsGVFSConfig) { this.CopyFile(GVFSPlatform.Instance.GetSecureDataRootForGVFS(), archiveFolderPath, LocalGVFSConfig.FileName);