@@ -48,14 +48,6 @@ public List<IDependency> ListDependencies()
4848
4949internal class KinectRuntime : IDependency
5050{
51- private const string WixDownloadUrl =
52- "https://github.com/wixtoolset/wix3/releases/download/wix3112rtm/wix311-binaries.zip" ;
53-
54- private const string RuntimeDownloadUrl =
55- "https://download.microsoft.com/download/A/7/4/A74239EB-22C2-45A1-996C-2F8E564B28ED/KinectRuntime-v2.0_1409-Setup.exe" ;
56-
57- private string TemporaryFolderName { get ; } = Guid . NewGuid ( ) . ToString ( ) . ToUpper ( ) ;
58-
5951 public IDependencyInstaller . ILocalizationHost Host { get ; set ; }
6052
6153 public string Name { get ; set ; }
@@ -96,275 +88,16 @@ public string InstallerEula
9688 }
9789 }
9890
99- public async Task < bool > Install ( IProgress < InstallationProgress > progress , CancellationToken cancellationToken )
91+ public Task < bool > Install ( IProgress < InstallationProgress > progress , CancellationToken cancellationToken )
10092 {
10193 // Amethyst will handle this exception for us anyway
10294 cancellationToken . ThrowIfCancellationRequested ( ) ;
10395
104- return
105- // Download and unpack WiX
106- await SetupWix ( "WiXToolset" , progress , cancellationToken ) &&
107-
108- // Download, unpack, and install the runtime
109- await SetupRuntime ( "WiXToolset" , progress , cancellationToken ) ;
110- }
111-
112- private async Task < StorageFolder > GetTempDirectory ( )
113- {
114- return await ApplicationData . Current . TemporaryFolder . CreateFolderAsync (
115- TemporaryFolderName , CreationCollisionOption . OpenIfExists ) ;
116- }
117-
118- private async Task < bool > SetupWix ( string outputFolder ,
119- IProgress < InstallationProgress > progress , CancellationToken cancellationToken )
120- {
121- // Amethyst will handle this exception for us anyway
122- cancellationToken . ThrowIfCancellationRequested ( ) ;
123-
124- try
96+ return Task . FromResult ( InstallFiles ( new [ ]
12597 {
126- using var client = new RestClient ( ) ;
127- progress . Report ( new InstallationProgress
128- {
129- IsIndeterminate = true ,
130- StageTitle = Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Downloading/WiX" ) ??
131- "Downloading WiX Toolset"
132- } ) ;
133-
134- // Create a stream reader using the received Installer Uri
135- await using var stream =
136- await client . ExecuteDownloadStreamAsync ( WixDownloadUrl , new RestRequest ( ) ) ;
137-
138- // Replace or create our installer file
139- var installerFile = await ( await GetTempDirectory ( ) ) . CreateFileAsync (
140- "wix-binaries.zip" , CreationCollisionOption . ReplaceExisting ) ;
141-
142- // Create an output stream and push all the available data to it
143- await using var fsInstallerFile = await installerFile . OpenStreamForWriteAsync ( ) ;
144- await stream . CopyToWithProgressAsync ( fsInstallerFile , cancellationToken ,
145- innerProgress =>
146- {
147- progress . Report ( new InstallationProgress
148- {
149- IsIndeterminate = false ,
150- OverallProgress = innerProgress / 34670186.0 ,
151- StageTitle = Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Downloading/WiX" ) ??
152- "Downloading WiX Toolset"
153- } ) ;
154- } ) ; // The runtime will do the rest for us
155-
156- // Close the file to unlock it
157- fsInstallerFile . Close ( ) ;
158-
159- var sourceZip = Path . GetFullPath ( Path . Combine ( ( await GetTempDirectory ( ) ) . Path , "wix-binaries.zip" ) ) ;
160- var tempDirectory = Path . GetFullPath ( Path . Combine ( ( await GetTempDirectory ( ) ) . Path , outputFolder ) ) ;
161-
162- if ( File . Exists ( sourceZip ) )
163- {
164- if ( ! Directory . Exists ( tempDirectory ) )
165- Directory . CreateDirectory ( tempDirectory ) ;
166-
167- try
168- {
169- // Extract the toolset
170- ZipFile . ExtractToDirectory ( sourceZip , tempDirectory , true ) ;
171- }
172- catch ( Exception e )
173- {
174- progress . Report ( new InstallationProgress
175- {
176- IsIndeterminate = true ,
177- StageTitle =
178- ( Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Exceptions/WiX/Extraction" ) ??
179- "Toolset extraction failed! Exception: {0}" ) . Replace ( "{0}" , e . Message )
180- } ) ;
181-
182- return false ;
183- }
184-
185- return true ;
186- }
187- }
188- catch ( Exception e )
189- {
190- progress . Report ( new InstallationProgress
191- {
192- IsIndeterminate = true ,
193- StageTitle = ( Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Exceptions/WiX/Installation" ) ??
194- "Toolset installation failed! Exception: {0}" ) . Replace ( "{0}" , e . Message )
195- } ) ;
196- return false ;
197- }
198-
199- return false ;
200- }
201-
202- private async Task < bool > SetupRuntime ( string wixFolder ,
203- IProgress < InstallationProgress > progress , CancellationToken cancellationToken )
204- {
205- // Amethyst will handle this exception for us anyway
206- cancellationToken . ThrowIfCancellationRequested ( ) ;
207-
208- try
209- {
210- using var client = new RestClient ( ) ;
211- progress . Report ( new InstallationProgress
212- {
213- IsIndeterminate = true ,
214- StageTitle = Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Downloading/Runtime" ) ??
215- "Downloading Kinect for Xbox One Runtime..."
216- } ) ;
217-
218- // Create a stream reader using the received Installer Uri
219- await using var stream =
220- await client . ExecuteDownloadStreamAsync ( RuntimeDownloadUrl , new RestRequest ( ) ) ;
221-
222- // Replace or create our installer file
223- var installerFile = await ( await GetTempDirectory ( ) ) . CreateFileAsync (
224- "kinect-setup.exe" , CreationCollisionOption . ReplaceExisting ) ;
225-
226- // Create an output stream and push all the available data to it
227- await using var fsInstallerFile = await installerFile . OpenStreamForWriteAsync ( ) ;
228- await stream . CopyToWithProgressAsync ( fsInstallerFile , cancellationToken ,
229- innerProgress =>
230- {
231- progress . Report ( new InstallationProgress
232- {
233- IsIndeterminate = false ,
234- OverallProgress = innerProgress / 93314296.0 ,
235- StageTitle = Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Downloading/Runtime" ) ??
236- "Downloading Kinect for Xbox One Runtime..."
237- } ) ;
238- } ) ; // The runtime will do the rest for us
239-
240- // Close the file to unlock it
241- fsInstallerFile . Close ( ) ;
242-
243- return
244- // Extract all runtime files for the installation
245- await ExtractFiles ( Path . GetFullPath ( Path . Combine ( ( await GetTempDirectory ( ) ) . Path , wixFolder ) ) ,
246- installerFile . Path , Path . Join ( ( await GetTempDirectory ( ) ) . Path , "KinectRuntime" ) ,
247- progress , cancellationToken ) &&
248-
249- // Install the files using msi installers
250- InstallFiles ( Directory . GetFiles ( Path . Join ( ( await GetTempDirectory ( ) ) . Path ,
251- "KinectRuntime" , "AttachedContainer" ) , "*.msi" ) ,
252- progress , cancellationToken ) ;
253- }
254- catch ( Exception e )
255- {
256- progress . Report ( new InstallationProgress
257- {
258- IsIndeterminate = true ,
259- StageTitle =
260- ( Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Exceptions/Runtime/Installation" ) ??
261- "Runtime installation failed! Exception: {0}" ) . Replace ( "{0}" , e . Message )
262- } ) ;
263- return false ;
264- }
265- }
266-
267- private async Task < bool > ExtractFiles ( string wixPath , string sourceFile , string outputFolder ,
268- IProgress < InstallationProgress > progress , CancellationToken cancellationToken )
269- {
270- // Amethyst will handle this exception for us anyway
271- cancellationToken . ThrowIfCancellationRequested ( ) ;
272-
273- try
274- {
275- progress . Report ( new InstallationProgress
276- {
277- IsIndeterminate = true ,
278- StageTitle = ( Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Unpacking" ) ??
279- "Unpacking {0}..." ) . Replace ( "{0}" , Path . GetFileName ( sourceFile ) )
280- } ) ;
281-
282- // dark.exe {sourceFile} -x {outDir}
283- var procStart = new ProcessStartInfo
284- {
285- FileName = Path . Combine ( wixPath , "dark.exe" ) ,
286- WorkingDirectory = ( await GetTempDirectory ( ) ) . Path ,
287- Arguments = $ "\" { sourceFile } \" -x \" { outputFolder } \" ",
288- CreateNoWindow = true ,
289- WindowStyle = ProcessWindowStyle . Hidden ,
290-
291- // Verbose error handling
292- RedirectStandardOutput = true ,
293- RedirectStandardError = true ,
294- RedirectStandardInput = false ,
295- UseShellExecute = false ,
296- StandardOutputEncoding = Encoding . UTF8 ,
297- StandardErrorEncoding = Encoding . UTF8
298- } ;
299-
300- var proc = Process . Start ( procStart ) ;
301- // Redirecting process output so that we can log what happened
302- var stdout = new StringBuilder ( ) ;
303- var stderr = new StringBuilder ( ) ;
304-
305- proc ! . OutputDataReceived += ( _ , args ) =>
306- {
307- if ( args . Data != null )
308- stdout . AppendLine ( args . Data ) ;
309- } ;
310- proc . ErrorDataReceived += ( _ , args ) =>
311- {
312- if ( args . Data != null )
313- stderr . AppendLine ( args . Data ) ;
314- } ;
315-
316- proc . BeginErrorReadLine ( ) ;
317- proc . BeginOutputReadLine ( ) ;
318- var hasExited = proc . WaitForExit ( 60000 ) ;
319-
320- // https://github.com/wixtoolset/wix3/blob/6b461364c40e6d1c487043cd0eae7c1a3d15968c/src/tools/dark/dark.cs#L54
321- // Exit codes for DARK:
322- //
323- // 0 - Success
324- // 1 - Error
325- // Just in case
326- if ( ! hasExited )
327- {
328- // WTF
329- progress . Report ( new InstallationProgress
330- {
331- IsIndeterminate = true ,
332- StageTitle =
333- Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Dark/Error/Timeout" ) ??
334- "Failed to execute dark.exe in the allocated time!"
335- } ) ;
336-
337- proc . Kill ( ) ;
338- }
339-
340- if ( proc . ExitCode == 1 )
341- {
342- // Assume WiX failed
343- progress . Report ( new InstallationProgress
344- {
345- IsIndeterminate = true ,
346- StageTitle =
347- ( Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Dark/Error/Result" ) ??
348- "Dark.exe exited with error code: {0}" ) . Replace ( "{0}" , proc . ExitCode . ToString ( ) )
349- } ) ;
350-
351- return false ;
352- }
353- }
354- catch ( Exception e )
355- {
356- progress . Report ( new InstallationProgress
357- {
358- IsIndeterminate = true ,
359- StageTitle =
360- ( Host ? . RequestLocalizedString ( "/Plugins/KinectOne/Stages/Exceptions/Other" ) ??
361- "Exception: {0}" ) . Replace ( "{0}" , e . Message )
362- } ) ;
363-
364- return false ;
365- }
366-
367- return true ;
98+ Path . Join ( Directory . GetParent ( Assembly . GetExecutingAssembly ( ) . Location ) ! . FullName ,
99+ "Assets" , "Resources" , "Dependencies" , "KinectRuntime-x64.msi" )
100+ } , progress , cancellationToken ) ) ;
368101 }
369102
370103 private bool InstallFiles ( IEnumerable < string > files ,
0 commit comments