@@ -12,6 +12,7 @@ namespace GVFS.FunctionalTests.Tools
1212 public static class GVFSServiceProcess
1313 {
1414 private static readonly string ServiceNameArgument = "--servicename=" + TestServiceName ;
15+ private static Process consoleServiceProcess ;
1516
1617 public static string TestServiceName
1718 {
@@ -22,10 +23,145 @@ public static string TestServiceName
2223 }
2324
2425 public static void InstallService ( )
26+ {
27+ if ( GVFSTestConfig . IsDevMode )
28+ {
29+ StartServiceAsConsoleProcess ( ) ;
30+ }
31+ else
32+ {
33+ InstallWindowsService ( ) ;
34+ }
35+ }
36+
37+ public static void UninstallService ( )
38+ {
39+ if ( GVFSTestConfig . IsDevMode )
40+ {
41+ StopConsoleServiceProcess ( ) ;
42+ CleanupServiceData ( ) ;
43+ }
44+ else
45+ {
46+ UninstallWindowsService ( ) ;
47+ }
48+ }
49+
50+ public static void StartService ( )
51+ {
52+ if ( GVFSTestConfig . IsDevMode )
53+ {
54+ StartServiceAsConsoleProcess ( ) ;
55+ }
56+ else
57+ {
58+ StartWindowsService ( ) ;
59+ }
60+ }
61+
62+ public static void StopService ( )
63+ {
64+ if ( GVFSTestConfig . IsDevMode )
65+ {
66+ StopConsoleServiceProcess ( ) ;
67+ }
68+ else
69+ {
70+ StopWindowsService ( ) ;
71+ }
72+ }
73+
74+ private static void StartServiceAsConsoleProcess ( )
75+ {
76+ StopConsoleServiceProcess ( ) ;
77+
78+ string pathToService = GetPathToService ( ) ;
79+ Console . WriteLine ( "Starting test service in console mode: " + pathToService ) ;
80+
81+ ProcessStartInfo startInfo = new ProcessStartInfo ( pathToService ) ;
82+ startInfo . Arguments = $ "--console { ServiceNameArgument } ";
83+ startInfo . UseShellExecute = false ;
84+ startInfo . CreateNoWindow = true ;
85+ startInfo . RedirectStandardOutput = true ;
86+ startInfo . RedirectStandardError = true ;
87+
88+ consoleServiceProcess = Process . Start ( startInfo ) ;
89+ consoleServiceProcess . ShouldNotBeNull ( "Failed to start test service process" ) ;
90+
91+ // Consume output asynchronously to prevent buffer deadlock
92+ consoleServiceProcess . BeginOutputReadLine ( ) ;
93+ consoleServiceProcess . BeginErrorReadLine ( ) ;
94+
95+ // Wait for the service to start listening on its named pipe
96+ string pipeName = TestServiceName + ".pipe" ;
97+ int retries = 50 ;
98+ while ( retries -- > 0 )
99+ {
100+ if ( consoleServiceProcess . HasExited )
101+ {
102+ throw new InvalidOperationException (
103+ $ "Test service process exited with code { consoleServiceProcess . ExitCode } before becoming ready") ;
104+ }
105+
106+ if ( File . Exists ( @"\\.\pipe\" + pipeName ) )
107+ {
108+ Console . WriteLine ( "Test service is ready (pipe: " + pipeName + ")" ) ;
109+ return ;
110+ }
111+
112+ Thread . Sleep ( 200 ) ;
113+ }
114+
115+ throw new System . TimeoutException ( "Timed out waiting for test service pipe: " + pipeName ) ;
116+ }
117+
118+ private static void StopConsoleServiceProcess ( )
119+ {
120+ if ( consoleServiceProcess != null && ! consoleServiceProcess . HasExited )
121+ {
122+ try
123+ {
124+ Console . WriteLine ( "Stopping test service console process (PID: " + consoleServiceProcess . Id + ")" ) ;
125+ consoleServiceProcess . Kill ( ) ;
126+ consoleServiceProcess . WaitForExit ( 5000 ) ;
127+ }
128+ catch ( InvalidOperationException )
129+ {
130+ // Process already exited
131+ }
132+
133+ consoleServiceProcess = null ;
134+ }
135+ }
136+
137+ private static void CleanupServiceData ( )
138+ {
139+ string commonAppDataRoot = Environment . GetEnvironmentVariable ( "GVFS_COMMON_APPDATA_ROOT" ) ;
140+ string serviceData ;
141+ if ( ! string . IsNullOrEmpty ( commonAppDataRoot ) )
142+ {
143+ serviceData = Path . Combine ( commonAppDataRoot , TestServiceName ) ;
144+ }
145+ else
146+ {
147+ serviceData = Path . Combine (
148+ Environment . GetFolderPath ( Environment . SpecialFolder . CommonApplicationData ) ,
149+ "GVFS" ,
150+ TestServiceName ) ;
151+ }
152+
153+ DirectoryInfo serviceDataDir = new DirectoryInfo ( serviceData ) ;
154+ if ( serviceDataDir . Exists )
155+ {
156+ serviceDataDir . Delete ( true ) ;
157+ }
158+ }
159+
160+ private static void InstallWindowsService ( )
25161 {
26162 Console . WriteLine ( "Installing " + TestServiceName ) ;
27163
28- UninstallService ( ) ;
164+ UninstallWindowsService ( ) ;
29165
30166 // Wait for delete to complete. If the services control panel is open, this will never complete.
31167 while ( RunScCommand ( "query" , TestServiceName ) . ExitCode == 0 )
@@ -47,12 +183,12 @@ public static void InstallService()
47183 ProcessResult result = RunScCommand ( "create" , createServiceArguments ) ;
48184 result . ExitCode . ShouldEqual ( 0 , "Failure while running sc create " + createServiceArguments + "\r \n " + result . Output ) ;
49185
50- StartService ( ) ;
186+ StartWindowsService ( ) ;
51187 }
52188
53- public static void UninstallService ( )
189+ private static void UninstallWindowsService ( )
54190 {
55- StopService ( ) ;
191+ StopWindowsService ( ) ;
56192
57193 RunScCommand ( "delete" , TestServiceName ) ;
58194
@@ -65,7 +201,7 @@ public static void UninstallService()
65201 }
66202 }
67203
68- public static void StartService ( )
204+ private static void StartWindowsService ( )
69205 {
70206 ServiceController testService = ServiceController . GetServices ( ) . SingleOrDefault ( service => service . ServiceName == TestServiceName ) ;
71207 testService . ShouldNotBeNull ( $ "{ TestServiceName } does not exist as a service") ;
@@ -78,7 +214,7 @@ public static void StartService()
78214 }
79215 }
80216
81- public static void StopService ( )
217+ private static void StopWindowsService ( )
82218 {
83219 try
84220 {
0 commit comments