예제 #1
0
        /// <summary> The internal implementation of the execute task </summary>
        /// <returns> ErrorCodes.Success if succeeds, one of the other ErrorCodes otherwise </returns>
        internal int InternalExecute()
        {
            bool             isTargetRuntimeManaged    = TargetRuntime.Equals("Managed", StringComparison.OrdinalIgnoreCase);
            List <ITaskItem> currentAppxPackagePayload = AppxPackagePayload.ToList();
            string           transformedAppxManifest   = Path.Combine(OutputPath, "AppxManifest.xml");

            // Perform setup:
            //   - Create output directory if it does not already exist
            //   - Delete existing AppxManifest.xml if it exists
            try
            {
                Directory.CreateDirectory(OutputPath);
                File.Delete(transformedAppxManifest);
            }
            catch (PathTooLongException)
            {
                Log.LogError(Resources.Error_PathTooLongExceptionOutputFolder);
                return((int)ErrorCodes.PathTooLongException);
            }
            catch (IOException ioException)
            {
                Log.LogError(Resources.Error_IOExceptionOutputFolder, ioException.Message);
                return((int)ErrorCodes.InputFileReadError);
            }
            catch (Exception e)
            {
                Log.LogError(Resources.Error_InternalWireUpCoreRuntimeError, e.Message);
                return((int)ErrorCodes.InternalWireUpCoreRuntimeError);
            }

            // Apply transformations required to hook up the Core Runtime
            // 1. For Managed apps, move <app.exe> to [AppEntryPointDir]\<app.exe> and copy UWPShim.exe to package root as <app.exe>
            // 2. Replace all ClrHost.dll with either UWPShim.exe (for hybrid apps) or <app.exe> (for managed apps)
            // 3. If #2 above is performed, inject UWPShim.exe into the output directory for unmanaged apps
            //    which contain managed winmd and for managed background tasks (which do not contain entrypoint exe)
            // 4. If #1 or #2 above is performed, add a package dependency to CoreRuntime framework package.

            using (StreamReader sr = new StreamReader(AppxManifest))
            {
                XDocument  doc             = XDocument.Load(sr, LoadOptions.None);
                XNamespace ns              = @"http://schemas.microsoft.com/appx/manifest/foundation/windows10";
                string     inprocServer    = UWPShimEXE;
                var        uwpShimLocation = Path.Combine(new [] {
                    CoreRuntimeSDKLocation,
                    "AppLocal",
                    UWPShimEXE
                });

                IEnumerable <XAttribute> entryPointExecutables = Enumerable.Empty <XAttribute>();
                if (isTargetRuntimeManaged)
                {
                    // 1. For Managed apps, move <app.exe> to [AppEntryPointDir]\<app.exe> and copy UWPShim.exe to package root as <app.exe>
                    entryPointExecutables = doc.Descendants(ns + "Applications").Descendants(ns + "Application").Where(x => x.Attribute("Executable") != null).Select(x => x.Attribute("Executable"));

                    if (entryPointExecutables.Any())
                    {
                        // Set the inprocServer to the <app.exe>. From this point on that's our UWPShim.exe
                        // and since we will be copying uwpShim possibly several times with different names, yet they are all
                        // uwpshim.exe, it's OK to grab the first one and use it as inprocserver entry
                        inprocServer = entryPointExecutables.First().Value;
                        if (entryPointExecutables.Any(x => x.Value.Contains(Path.DirectorySeparatorChar)))
                        {
                            Log.LogError(Resources.Error_CustomEntryPointNotSupported);
                            return((int)ErrorCodes.NotSupported);
                        }

                        foreach (var entryPointExecutable in entryPointExecutables)
                        {
                            // Do not copy <app.exe> from original location, just modify TargetPath to [AppEntryPointDir]\<app.exe>
                            ITaskItem currentManagedEntryPointExecutableTaskItem = AppxPackagePayload.Where(x => x.GetMetadata("TargetPath") == entryPointExecutable.Value).Single();
                            currentManagedEntryPointExecutableTaskItem.SetMetadata("TargetPath", AppEntryPointDir + "\\" + entryPointExecutable.Value);

                            // Copy UWPShim
                            var entryPointExecutableShim = Path.Combine(OutputPath, entryPointExecutable.Value);
                            File.Copy(uwpShimLocation, entryPointExecutableShim, true);
                            var copyResourcesReturncode = CopyWin32Resources(currentManagedEntryPointExecutableTaskItem.ItemSpec, entryPointExecutableShim);
                            if (copyResourcesReturncode != 0)
                            {
                                Log.LogError(Resources.Error_CopyWin32ResourcesFailed, copyResourcesReturncode);
                                return((int)ErrorCodes.CoreRuntimeLinkageError);
                            }

                            // Add UWPShim to appx package payload
                            ITaskItem entryPointExecutableShimTaskItem = new TaskItem(entryPointExecutableShim);
                            entryPointExecutableShimTaskItem.SetMetadata("TargetPath", entryPointExecutable.Value);
                            currentManagedEntryPointExecutableTaskItem.CopyMetadataTo(entryPointExecutableShimTaskItem);
                            currentAppxPackagePayload.Add(entryPointExecutableShimTaskItem);
                        }
                    }
                }

                //
                // 2. Replace all ClrHost.dll with either UWPShim.exe (for hybrid apps) or <app.exe> (for managed apps)
                var inprocServerNodes = doc.DescendantNodes().OfType <XText>()
                                        .Where(x => x.Value.Equals("ClrHost.dll", StringComparison.OrdinalIgnoreCase))
                                        .Select(x => x);

                bool bHasManagedWinMD = false;
                foreach (var node in inprocServerNodes)
                {
                    node.Value       = inprocServer;
                    bHasManagedWinMD = true;
                }

                //
                // 3. If #2 above is performed, inject UWPShim.exe into the output directory for unmanaged apps
                //    which contain managed winmd and for managed background tasks (which do not contain entrypoint exe)
                if (bHasManagedWinMD && inprocServer.Equals(UWPShimEXE))
                {
                    try
                    {
                        // Copy UWPShim
                        string uwpDestination = Path.Combine(OutputPath, inprocServer);
                        File.Copy(uwpShimLocation, uwpDestination, true);

                        // Add UWPShim to appx package payload
                        TaskItem uwpShimTaskItem = new TaskItem(uwpDestination);
                        uwpShimTaskItem.SetMetadata("TargetPath", inprocServer);
                        currentAppxPackagePayload.Add(uwpShimTaskItem);
                    }
                    catch (Exception exception)
                    {
                        Log.LogError(Resources.Error_UnspecifiedCreatingUWPShimForHybrid, exception.Message);
                        return((int)ErrorCodes.CoreRuntimeLinkageError);
                    }
                }

                //
                // 4. If #1 or #2 above is performed, add a package dependency to CoreRuntime framework package.
                if (isTargetRuntimeManaged || bHasManagedWinMD)
                {
                    foreach (var FrameworkPackage in FrameworkPackages)
                    {
                        string FrameworkPackageName       = FrameworkPackage.GetMetadata("Name");
                        string FrameworkPackageMinVersion = FrameworkPackage.GetMetadata("Version");
                        string FrameworkPackagePublisher  = FrameworkPackage.GetMetadata("Publisher");
                        if (!doc.Descendants(ns + "PackageDependency").Any(x => x.Attributes("Name").SingleOrDefault().Value == FrameworkPackageName))
                        {
                            // There aren't any such PackageDependency. Add it now.
                            XElement packageDependency = new XElement(
                                ns + "PackageDependency",
                                new XAttribute("Name", FrameworkPackageName),
                                new XAttribute("MinVersion", FrameworkPackageMinVersion),
                                new XAttribute("Publisher", FrameworkPackagePublisher)
                                );
                            doc.Descendants(ns + "Dependencies").SingleOrDefault().Add(packageDependency);
                            FrameworkPackagesNeedsToBeDeployed = true;
                        }
                    }
                }

                doc.Save(transformedAppxManifest);
            }

            TransformedAppxPackagePayload = currentAppxPackagePayload.ToArray();
            return((int)ErrorCodes.Success);
        }