Dela via


Hantera Universal Windows-projekt

Universella Windows-appar är appar som riktar sig till både Windows 8.1 och Windows Phone 8.1, vilket gör det möjligt för utvecklare att använda kod och andra tillgångar på båda plattformarna. Den delade koden och resurserna sparas i ett delat projekt, medan den plattformsspecifika koden och resurserna sparas i separata projekt, en för Windows och den andra för Windows Phone. Mer information om universella Windows-appar finns i Universella Windows-appar. Visual Studio-tillägg som hanterar projekt bör vara medvetna om att universella Windows-appprojekt har en struktur som skiljer sig från appar med en plattform. Den här genomgången visar hur du navigerar i det delade projektet och hanterar de delade objekten.

  1. Skapa ett C#VSIX-projekt med namnet TestUniversalProject. (Fil>Ny>Project och sedan C#>Extensibility>Visual Studio Package). Lägg till en projektobjektmall för anpassat kommando (högerklicka på projektnoden i Solution Explorer och välj Lägg till>nytt objekt och gå sedan till Utökningsbarhet). Ge filen namnet TestUniversalProject.

  2. Lägg till en referens till Microsoft.VisualStudio.Shell.Interop.12.1.DesignTime.dll och Microsoft.VisualStudio.Shell.Interop.14.0.DesignTime.dll (i avsnittet Tillägg ).

  3. Öppna TestUniversalProject.cs och lägg till följande using direktiv:

    using EnvDTE;
    using EnvDTE80;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.PlatformUI;
    using Microsoft.Internal.VisualStudio.PlatformUI;
    using System.Collections.Generic;
    using System.IO;
    using System.Windows.Forms;
    
  4. I klassen TestUniversalProject lägger du till ett privat fält som pekar på utdatafönstret .

    public sealed class TestUniversalProject
    {
        IVsOutputWindowPane output;
    . . .
    }
    
  5. Ange referensen till utdatafönstret i konstruktorn TestUniversalProject:

    private TestUniversalProject(Package package)
    {
        if (package == null)
        {
            throw new ArgumentNullException("package");
        }
    
        this.package = package;
    
        OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
        if (commandService != null)
        {
            CommandID menuCommandID = new CommandID(MenuGroup, CommandId);
            EventHandler eventHandler = this.ShowMessageBox;
            MenuCommand menuItem = new MenuCommand(eventHandler, menuCommandID);
            commandService.AddCommand(menuItem);
        }
    
        // get a reference to the Output window
        output = (IVsOutputWindowPane)ServiceProvider.GetService(typeof(SVsGeneralOutputWindowPane));
    }
    
  6. Ta bort den befintliga koden från ShowMessageBox metoden:

    private void ShowMessageBox(object sender, EventArgs e)
    {
    }
    
  7. Hämta DTE-objektet, som vi kommer att använda för flera olika syften i den här genomgången. Kontrollera också att en lösning läses in när menyknappen klickas.

    private void ShowMessageBox(object sender, EventArgs e)
    {
        var dte = (EnvDTE.DTE)this.ServiceProvider.GetService(typeof(EnvDTE.DTE));
        if (dte.Solution != null)
        {
            . . .
        }
        else
        {
            MessageBox.Show("No solution is open");
            return;
        }
    }
    
  8. Hitta det delade projektet. Det delade projektet är en ren container. den skapar eller producerar inte utdata. Följande metod hittar det första delade projektet i lösningen genom att leta efter objektet IVsHierarchy som har funktionen delat projekt.

    private IVsHierarchy FindSharedProject()
    {
        var sln = (IVsSolution)this.ServiceProvider.GetService(typeof(SVsSolution));
        Guid empty = Guid.Empty;
        IEnumHierarchies enumHiers;
    
        //get all the projects in the solution
        ErrorHandler.ThrowOnFailure(sln.GetProjectEnum((uint)__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION, ref empty, out enumHiers));
        foreach (IVsHierarchy hier in ComUtilities.EnumerableFrom(enumHiers))
        {
            if (PackageUtilities.IsCapabilityMatch(hier, "SharedAssetsProject"))
            {
                return hier;
            }
        }
        return null;
    }
    
  9. ShowMessageBox I -metoden matar du ut undertexten (projektnamnet som visas i Solution Explorer) för det delade projektet.

    private void ShowMessageBox(object sender, EventArgs e)
    {
        var dte = (DTE)this.ServiceProvider.GetService(typeof(DTE));
    
        if (dte.Solution != null)
        {
            var sharedHier = this.FindSharedProject();
            if (sharedHier != null)
            {
                string sharedCaption = HierarchyUtilities.GetHierarchyProperty<string>(sharedHier, (uint)VSConstants.VSITEMID.Root,
                     (int)__VSHPROPID.VSHPROPID_Caption);
                output.OutputStringThreadSafe(string.Format("Found shared project: {0}\n", sharedCaption));
            }
            else
            {
                MessageBox.Show("Solution has no shared project");
                return;
            }
        }
        else
        {
            MessageBox.Show("No solution is open");
            return;
        }
    }
    
  10. Hämta det aktiva plattformsprojektet. Plattformsprojekt är de projekt som innehåller plattformsspecifik kod och resurser. Följande metod använder det nya fältet VSHPROPID_SharedItemContextHierarchy för att hämta det aktiva plattformsprojektet.

    private IVsHierarchy GetActiveProjectContext(IVsHierarchy hierarchy)
    {
        IVsHierarchy activeProjectContext;
        if (HierarchyUtilities.TryGetHierarchyProperty(hierarchy, (uint)VSConstants.VSITEMID.Root,
             (int)__VSHPROPID7.VSHPROPID_SharedItemContextHierarchy, out activeProjectContext))
        {
            return activeProjectContext;
        }
        else
        {
            return null;
        }
    }
    
  11. ShowMessageBox I -metoden matar du ut beskrivningen av det aktiva plattformsprojektet.

    private void ShowMessageBox(object sender, EventArgs e)
    {
        var dte = (DTE)this.ServiceProvider.GetService(typeof(DTE));
    
        if (dte.Solution != null)
        {
            var sharedHier = this.FindSharedProject();
            if (sharedHier != null)
            {
                string sharedCaption = HierarchyUtilities.GetHierarchyProperty<string>(sharedHier, (uint)VSConstants.VSITEMID.Root,
                     (int)__VSHPROPID.VSHPROPID_Caption);
                output.OutputStringThreadSafe(string.Format("Shared project: {0}\n", sharedCaption));
    
                var activePlatformHier = this.GetActiveProjectContext(sharedHier);
                if (activePlatformHier != null)
                {
                    string activeCaption = HierarchyUtilities.GetHierarchyProperty<string>(activePlatformHier,
                         (uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID.VSHPROPID_Caption);
                    output.OutputStringThreadSafe(string.Format("Active platform project: {0}\n", activeCaption));
                }
                else
                {
                    MessageBox.Show("Shared project has no active platform project");
                }
            }
            else
            {
                MessageBox.Show("Solution has no shared project");
            }
        }
        else
        {
            MessageBox.Show("No solution is open");
        }
    }
    
  12. Iterera genom plattformsprojekten. Följande metod hämtar alla importprojekt (plattform) från det delade projektet.

    private IEnumerable<IVsHierarchy> EnumImportingProjects(IVsHierarchy hierarchy)
    {
        IVsSharedAssetsProject sharedAssetsProject;
        if (HierarchyUtilities.TryGetHierarchyProperty(hierarchy, (uint)VSConstants.VSITEMID.Root,
            (int)__VSHPROPID7.VSHPROPID_SharedAssetsProject, out sharedAssetsProject)
            && sharedAssetsProject != null)
        {
            foreach (IVsHierarchy importingProject in sharedAssetsProject.EnumImportingProjects())
            {
                yield return importingProject;
            }
        }
    }
    

    Viktigt!

    Om användaren har öppnat ett C++-universellt Windows-appprojekt i den experimentella instansen utlöser koden ovan ett undantag. Det här är ett känt problem. Undvik undantaget genom att foreach ersätta blocket ovan med följande:

    var importingProjects = sharedAssetsProject.EnumImportingProjects();
    for (int i = 0; i < importingProjects.Count; ++i)
    {
        yield return importingProjects[i];
    }
    
  13. ShowMessageBox-metoden, mata ut rubriken för varje plattformsprojekt. Infoga följande kod efter raden som matar ut beskrivningen av det aktiva plattformsprojektet. Endast de plattformsprojekt som läses in visas i den här listan.

    output.OutputStringThreadSafe("Platform projects:\n");
    
    IEnumerable<IVsHierarchy> projects = this.EnumImportingProjects(sharedHier);
    
    bool isActiveProjectSet = false;
    foreach (IVsHierarchy platformHier in projects)
    {
        string platformCaption = HierarchyUtilities.GetHierarchyProperty<string>(platformHier, (uint)VSConstants.VSITEMID.Root,
            (int)__VSHPROPID.VSHPROPID_Caption);
        output.OutputStringThreadSafe(string.Format(" * {0}\n", platformCaption));
    }
    
  14. Ändra det aktiva plattformsprojektet. Följande metod anger det aktiva projektet med .SetProperty

    private int SetActiveProjectContext(IVsHierarchy hierarchy, IVsHierarchy activeProjectContext)
    {
        return hierarchy.SetProperty((uint)VSConstants.VSITEMID.Root, (int)__VSHPROPID7.VSHPROPID_SharedItemContextHierarchy, activeProjectContext);
    }
    
  15. ShowMessageBox I metoden ändrar du det aktiva plattformsprojektet. Infoga den här koden i foreach blocket.

    bool isActiveProjectSet = false;
    string platformCaption = null;
    foreach (IVsHierarchy platformHier in projects)
    {
        platformCaption = HierarchyUtilities.GetHierarchyProperty<string>(platformHier, (uint)VSConstants.VSITEMID.Root,
             (int)__VSHPROPID.VSHPROPID_Caption);
        output.OutputStringThreadSafe(string.Format(" * {0}\n", platformCaption));
    
        // if this project is neither the shared project nor the current active platform project,
        // set it to be the active project
        if (!isActiveProjectSet && platformHier != activePlatformHier)
        {
            this.SetActiveProjectContext(sharedHier, platformHier);
            activePlatformHier = platformHier;
            isActiveProjectSet = true;
        }
    }
    output.OutputStringThreadSafe("set active project: " + platformCaption +'\n');
    
  16. Prova nu. Tryck på F5 för att starta den experimentella instansen. Skapa ett C# universal hub-appprojekt i den experimentella instansen (i dialogrutan Nytt projekt , Visual C#>Windows>Windows 8>Universal>Hub App). När lösningen har lästs in går du till menyn Verktyg och klickar på Anropa TestUniversalProject och kontrollerar sedan texten i fönstret Utdata . Du bör se något som liknar följande:

    Found shared project: HubApp.Shared
    The active platform project: HubApp.Windows
    Platform projects:
     * HubApp.Windows
     * HubApp.WindowsPhone
    set active project: HubApp.WindowsPhone
    

Hantera delade objekt i plattformsprojektet

  1. Hitta de delade objekten i plattformsprojektet. Objekten i det delade projektet visas i plattformsprojektet som delade objekt. Du kan inte se dem i Solution Explorer, men du kan gå till projekthierarkin för att hitta dem. Följande metod går igenom hierarkin och samlar in alla delade element. Du kan välja att mata ut etiketten för varje objekt. De delade objekten identifieras av den nya egenskapen VSHPROPID_IsSharedItem.

    private void InspectHierarchyItems(IVsHierarchy hier, uint itemid, int level, List<uint> itemIds, bool getSharedItems, bool printItems)
    {
        string caption = HierarchyUtilities.GetHierarchyProperty<string>(hier, itemid, (int)__VSHPROPID.VSHPROPID_Caption);
        if (printItems)
            output.OutputStringThreadSafe(string.Format("{0}{1}\n", new string('\t', level), caption));
    
        // if getSharedItems is true, inspect only shared items; if it's false, inspect only unshared items
        bool isSharedItem;
        if (HierarchyUtilities.TryGetHierarchyProperty(hier, itemid, (int)__VSHPROPID7.VSHPROPID_IsSharedItem, out isSharedItem)
            && (isSharedItem == getSharedItems))
        {
            itemIds.Add(itemid);
        }
    
        uint child;
        if (HierarchyUtilities.TryGetHierarchyProperty(hier, itemid, (int)__VSHPROPID.VSHPROPID_FirstChild, Unbox.AsUInt32, out child)
            && child != (uint)VSConstants.VSITEMID.Nil)
        {
            this.InspectHierarchyItems(hier, child, level + 1, itemIds, isSharedItem, printItems);
    
            while (HierarchyUtilities.TryGetHierarchyProperty(hier, child, (int)__VSHPROPID.VSHPROPID_NextSibling, Unbox.AsUInt32, out child)
                && child != (uint)VSConstants.VSITEMID.Nil)
            {
                this.InspectHierarchyItems(hier, child, level + 1, itemIds, isSharedItem, printItems);
            }
        }
    }
    
  2. ShowMessageBox I-metoden lägger du till följande kod för att gå igenom projekthierarkiobjekten för plattformen. Infoga den i foreach blocket.

    output.OutputStringThreadSafe("Walk the active platform project:\n");
    var sharedItemIds = new List<uint>();
    this.InspectHierarchyItems(activePlatformHier, (uint)VSConstants.VSITEMID.Root, 1, sharedItemIds, true, true);
    
  3. Läs de delade objekten. De delade objekten visas i plattformsprojektet som dolda länkade filer och du kan läsa alla egenskaper som vanliga länkade filer. Följande kod läser den fullständiga sökvägen för det första delade objektet.

    var sharedItemId = sharedItemIds[0];
    string fullPath;
    ErrorHandler.ThrowOnFailure(((IVsProject)activePlatformHier).GetMkDocument(sharedItemId, out fullPath));
    output.OutputStringThreadSafe(string.Format("Shared item full path: {0}\n", fullPath));
    
  4. Prova nu. Tryck på F5 för att starta den experimentella instansen. Skapa ett C#-universellt hubbprogramprojekt i den experimentella instansen (i dialogrutan Nytt projekt går Visual C#>Windows>Windows 8>Universal>Hub App) till menyn Verktyg och klickar på Anropa TestUniversalProject och markerar sedan texten i fönstret Utdata . Du bör se något som liknar följande:

    Found shared project: HubApp.Shared
    The active platform project: HubApp.Windows
    Platform projects:
     * HubApp.Windows
     * HubApp.WindowsPhone
    set active project: HubApp.WindowsPhone
    Walk the active platform project:
        HubApp.WindowsPhone
            <HubApp.Shared>
                App.xaml
                    App.xaml.cs
                Assets
                    DarkGray.png
                    LightGray.png
                    MediumGray.png
                Common
                    NavigationHelper.cs
                    ObservableDictionary.cs
                    RelayCommand.cs
                    SuspensionManager.cs
                DataModel
                    SampleData.json
                    SampleDataSource.cs
                HubApp.Shared.projitems
                Strings
                    en-US
                        Resources.resw
            Assets
                HubBackground.theme-dark.png
                HubBackground.theme-light.png
                Logo.scale-240.png
                SmallLogo.scale-240.png
                SplashScreen.scale-240.png
                Square71x71Logo.scale-240.png
                StoreLogo.scale-240.png
                WideLogo.scale-240.png
            HubPage.xaml
                HubPage.xaml.cs
            ItemPage.xaml
                ItemPage.xaml.cs
            Package.appxmanifest
            Properties
                AssemblyInfo.cs
            References
                .NET for Windows Store apps
                HubApp.Shared
                Windows Phone 8.1
            SectionPage.xaml
                SectionPage.xaml.cs
    

Identifiera ändringar i plattformsprojekt och delade projekt

  1. Du kan använda hierarki- och projekthändelser för att identifiera ändringar i delade projekt, precis som för plattformsprojekt. Projektobjekten i det delade projektet visas dock inte, vilket innebär att vissa händelser inte utlöses när delade projektobjekt ändras.

    Överväg händelsesekvensen när en fil i ett projekt byter namn:

    1. Filnamnet ändras på disken.

    2. Projektfilen uppdateras så att den innehåller det nya namnet på filen.

      Hierarkihändelser (till exempel IVsHierarchyEvents) spårar vanligtvis de ändringar som visas i användargränssnittet, som i Solution Explorer. Hierarkihändelser anser att en filbytesåtgärd består av en filborttagning och sedan ett filtillägg. Men när osynliga objekt ändras utlöser hierarkihändelsesystemet en OnItemDeleted händelse men inte en OnItemAdded händelse. Om du byter namn på en fil i ett plattformsprojekt får du därför både OnItemDeleted och OnItemAdded, men om du byter namn på en fil i ett delat projekt får du bara OnItemDeleted.

      Om du vill spåra ändringar i projektobjekt kan du hantera DTE-projektobjekthändelser (de som finns i ProjectItemsEventsClass). Men om du hanterar ett stort antal händelser kan du få bättre prestanda när du hanterar händelserna i IVsTrackProjectDocuments2. I den här genomgången visar vi bara hierarkihändelserna och DTE-händelserna. I den här proceduren lägger du till en händelselyssnare i ett delat projekt och ett plattformsprojekt. När du sedan byter namn på en fil i ett delat projekt och en annan fil i ett plattformsprojekt kan du se de händelser som utlöses för varje namnbytesåtgärd.

      I den här proceduren lägger du till en händelselyssnare i ett delat projekt och ett plattformsprojekt. När du sedan byter namn på en fil i ett delat projekt och en annan fil i ett plattformsprojekt kan du se de händelser som utlöses för varje namnbytesåtgärd.

  2. Lägg till en händelselyssnare. Lägg till en ny klassfil i projektet och anropa den HierarchyEventListener.cs.

  3. Öppna filen HierarchyEventListener.cs och lägg till följande med hjälp av direktiv:

    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.VisualStudio;
    using System.IO;
    
  4. HierarchyEventListener Låt klassen implementera IVsHierarchyEvents:

    class HierarchyEventListener : IVsHierarchyEvents
    { }
    
  5. Implementera medlemmarna i IVsHierarchyEvents, som i koden nedan.

    class HierarchyEventListener : IVsHierarchyEvents
    {
        private IVsHierarchy hierarchy;
        IVsOutputWindowPane output;
    
        internal HierarchyEventListener(IVsHierarchy hierarchy, IVsOutputWindowPane outputWindow) {
             this.hierarchy = hierarchy;
             this.output = outputWindow;
        }
    
        int IVsHierarchyEvents.OnInvalidateIcon(IntPtr hIcon) {
            return VSConstants.S_OK;
        }
    
        int IVsHierarchyEvents.OnInvalidateItems(uint itemIDParent) {
            return VSConstants.S_OK;
        }
    
        int IVsHierarchyEvents.OnItemAdded(uint itemIDParent, uint itemIDSiblingPrev, uint itemIDAdded) {
            output.OutputStringThreadSafe("IVsHierarchyEvents.OnItemAdded: " + itemIDAdded + "\n");
            return VSConstants.S_OK;
        }
    
        int IVsHierarchyEvents.OnItemDeleted(uint itemID) {
            output.OutputStringThreadSafe("IVsHierarchyEvents.OnItemDeleted: " + itemID + "\n");
            return VSConstants.S_OK;
        }
    
        int IVsHierarchyEvents.OnItemsAppended(uint itemIDParent) {
            output.OutputStringThreadSafe("IVsHierarchyEvents.OnItemsAppended\n");
            return VSConstants.S_OK;
        }
    
        int IVsHierarchyEvents.OnPropertyChanged(uint itemID, int propID, uint flags) {
            output.OutputStringThreadSafe("IVsHierarchyEvents.OnPropertyChanged: item ID " + itemID + "\n");
            return VSConstants.S_OK;
        }
    }
    
  6. I samma klass lägger du till en annan händelsehanterare för DTE-händelsen ItemRenamed, som inträffar när ett projektobjekt byter namn.

    public void OnItemRenamed(EnvDTE.ProjectItem projItem, string oldName)
    {
        output.OutputStringThreadSafe(string.Format("[Event] Renamed {0} to {1} in project {2}\n",
             oldName, Path.GetFileName(projItem.get_FileNames(1)), projItem.ContainingProject.Name));
    }
    
  7. Registrera dig för hierarkievenemangen. Du måste registrera dig separat för varje projekt som du spårar. Lägg till följande kod i ShowMessageBox, en för det delade projektet och den andra för ett av plattformsprojekten.

    // hook up the event listener for hierarchy events on the shared project
    HierarchyEventListener listener1 = new HierarchyEventListener(sharedHier, output);
    uint cookie1;
    sharedHier.AdviseHierarchyEvents(listener1, out cookie1);
    
    // hook up the event listener for hierarchy events on the
    active project
    HierarchyEventListener listener2 = new HierarchyEventListener(activePlatformHier, output);
    uint cookie2;
    activePlatformHier.AdviseHierarchyEvents(listener2, out cookie2);
    
  8. Registrera dig för DTE-projektobjekthändelsen ItemRenamed. Lägg till följande kod när du har kopplat in den andra lyssnaren.

    // hook up DTE events for project items
    Events2 dteEvents = (Events2)dte.Events;
    dteEvents.ProjectItemsEvents.ItemRenamed += listener1.OnItemRenamed;
    
  9. Ändra det delade objektet. Du kan inte ändra delade objekt i ett plattformsprojekt. I stället måste du ändra dem i det delade projektet som är den faktiska ägaren av dessa objekt. Du kan hämta motsvarande objekt-ID i det delade projektet med IsDocumentInProject, vilket ger det det delade objektets fullständiga sökväg. Sedan kan du ändra det delade objektet. Ändringen sprids till plattformsprojekten.

    Viktigt!

    Du bör ta reda på om ett projektobjekt är ett delat objekt innan du ändrar det.

    Följande metod ändrar namnet på en projektobjektfil.

    private void ModifyFileNameInProject(IVsHierarchy project, string path)
    {
        int found;
        uint projectItemID;
        VSDOCUMENTPRIORITY[] priority = new VSDOCUMENTPRIORITY[1];
        if (ErrorHandler.Succeeded(((IVsProject)project).IsDocumentInProject(path, out found, priority, out projectItemID))
            && found != 0)
        {
            var name = DateTime.Now.Ticks.ToString() + Path.GetExtension(path);
            project.SetProperty(projectItemID, (int)__VSHPROPID.VSHPROPID_EditLabel, name);
            output.OutputStringThreadSafe(string.Format("Renamed {0} to {1}\n", path,name));
        }
    }
    
  10. Anropa den här metoden efter all annan kod i ShowMessageBox för att ändra filnamnet för objektet i det delade projektet. Infoga detta efter koden som hämtar den fullständiga sökvägen för objektet i det delade projektet.

    // change the file name of an item in a shared project
    this.InspectHierarchyItems(activePlatformHier, (uint)VSConstants.VSITEMID.Root, 1, sharedItemIds, true, true);
    ErrorHandler.ThrowOnFailure(((IVsProject)activePlatformHier).GetMkDocument(sharedItemId, out fullPath));
    output.OutputStringThreadSafe(string.Format("Shared project item ID = {0}, full path = {1}\n", sharedItemId, fullPath));
    this.ModifyFileNameInProject(sharedHier, fullPath);
    
  11. Skapa och kör projektet. Skapa en universell C#-hubbapp i den experimentella instansen, gå till menyn Verktyg och klicka på Anropa TestUniversalProject och kontrollera texten i fönstret allmänna utdata. Namnet på det första objektet i det delade projektet (vi förväntar oss att det är Filen App.xaml ) bör ändras och du bör se att ItemRenamed händelsen har utlösts. I det här fallet, eftersom byta namn på App.xaml gör att App.xaml.cs också ska byta namn, bör du se fyra händelser (två för varje plattformsprojekt). (DTE-händelser spårar inte objekten i det delade projektet.) Du bör se två OnItemDeleted händelser (en för vart och ett av plattformsprojekten), men inga OnItemAdded händelser.

  12. Försök nu att byta namn på en fil i ett plattformsprojekt, så kan du se skillnaden i de händelser som utlöses. Lägg till följande kod i ShowMessageBox efter anropet till ModifyFileName.

    // change the file name of an item in a platform project
    var unsharedItemIds = new List<uint>();
    this.InspectHierarchyItems(activePlatformHier, (uint)VSConstants.VSITEMID.Root, 1, unsharedItemIds, false, false);
    
    var unsharedItemId = unsharedItemIds[0];
    string unsharedPath;
    ErrorHandler.ThrowOnFailure(((IVsProject)activePlatformHier).GetMkDocument(unsharedItemId, out unsharedPath));
    output.OutputStringThreadSafe(string.Format("Platform project item ID = {0}, full path = {1}\n", unsharedItemId, unsharedPath));
    
    this.ModifyFileNameInProject(activePlatformHier, unsharedPath);
    
  13. Skapa och kör projektet. Skapa ett C#-universellt projekt i den experimentella instansen, gå till menyn Verktyg och klicka på Anropa TestUniversalProject och kontrollera texten i fönstret allmänna utdata. När filen i plattformsprojektet har bytt namn bör du se både en OnItemAdded händelse och en OnItemDeleted händelse. Eftersom ändringen av filen inte påverkade andra filer, och eftersom ändringar av objekt i ett plattformsprojekt inte sprids till andra delar, finns det bara en sådan händelse.