├── .gitattributes
├── .gitignore
├── CortanaService
├── CortanaService.csproj
├── Properties
│ └── AssemblyInfo.cs
├── Service.cs
└── project.json
├── ExtensibilitySample.sln
├── ExtensibilitySample
├── App.xaml
├── App.xaml.cs
├── ApplicationInsights.config
├── Assets
│ ├── BadgeLogo.scale-100.png
│ ├── BadgeLogo.scale-200.png
│ ├── BadgeLogo.scale-400.png
│ ├── LockScreenLogo.scale-200.png
│ ├── SplashScreen.scale-200.png
│ ├── Square150x150Logo.scale-100.png
│ ├── Square150x150Logo.scale-200.png
│ ├── Square150x150Logo.scale-400.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Square44x44Logo.targetsize-24_altform-unplated.png
│ ├── Square44x44Logo.targetsize-48.png
│ ├── StoreLogo.png
│ ├── Wide310x150Logo.scale-200.png
│ └── Wide310x150Logo.scale-400.png
├── EditorTab.xaml
├── EditorTab.xaml.cs
├── ExtensibilitySample.csproj
├── ExtensibilitySampleCommands.xml
├── ExtensionManager.cs
├── ExtensionsTab.xaml
├── ExtensionsTab.xaml.cs
├── Image.xaml
├── Image.xaml.cs
├── ImageTools.cs
├── MainPage.xaml
├── MainPage.xaml.cs
├── Package.appxmanifest
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── Styles
│ └── Styles.xaml
├── Tab.cs
└── project.json
├── README.md
└── SECURITY.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | # DNX
42 | project.lock.json
43 | artifacts/
44 |
45 | *_i.c
46 | *_p.c
47 | *_i.h
48 | *.ilk
49 | *.meta
50 | *.obj
51 | *.pch
52 | *.pdb
53 | *.pgc
54 | *.pgd
55 | *.rsp
56 | *.sbr
57 | *.tlb
58 | *.tli
59 | *.tlh
60 | *.tmp
61 | *.tmp_proj
62 | *.log
63 | *.vspscc
64 | *.vssscc
65 | .builds
66 | *.pidb
67 | *.svclog
68 | *.scc
69 |
70 | # Chutzpah Test files
71 | _Chutzpah*
72 |
73 | # Visual C++ cache files
74 | ipch/
75 | *.aps
76 | *.ncb
77 | *.opensdf
78 | *.sdf
79 | *.cachefile
80 |
81 | # Visual Studio profiler
82 | *.psess
83 | *.vsp
84 | *.vspx
85 |
86 | # TFS 2012 Local Workspace
87 | $tf/
88 |
89 | # Guidance Automation Toolkit
90 | *.gpState
91 |
92 | # ReSharper is a .NET coding add-in
93 | _ReSharper*/
94 | *.[Rr]e[Ss]harper
95 | *.DotSettings.user
96 |
97 | # JustCode is a .NET coding add-in
98 | .JustCode
99 |
100 | # TeamCity is a build add-in
101 | _TeamCity*
102 |
103 | # DotCover is a Code Coverage Tool
104 | *.dotCover
105 |
106 | # NCrunch
107 | _NCrunch_*
108 | .*crunch*.local.xml
109 |
110 | # MightyMoose
111 | *.mm.*
112 | AutoTest.Net/
113 |
114 | # Web workbench (sass)
115 | .sass-cache/
116 |
117 | # Installshield output folder
118 | [Ee]xpress/
119 |
120 | # DocProject is a documentation generator add-in
121 | DocProject/buildhelp/
122 | DocProject/Help/*.HxT
123 | DocProject/Help/*.HxC
124 | DocProject/Help/*.hhc
125 | DocProject/Help/*.hhk
126 | DocProject/Help/*.hhp
127 | DocProject/Help/Html2
128 | DocProject/Help/html
129 |
130 | # Click-Once directory
131 | publish/
132 |
133 | # Publish Web Output
134 | *.[Pp]ublish.xml
135 | *.azurePubxml
136 | ## TODO: Comment the next line if you want to checkin your
137 | ## web deploy settings but do note that will include unencrypted
138 | ## passwords
139 | #*.pubxml
140 |
141 | *.publishproj
142 |
143 | # NuGet Packages
144 | *.nupkg
145 | # The packages folder can be ignored because of Package Restore
146 | **/packages/*
147 | # except build/, which is used as an MSBuild target.
148 | !**/packages/build/
149 | # Uncomment if necessary however generally it will be regenerated when needed
150 | #!**/packages/repositories.config
151 |
152 | # Windows Azure Build Output
153 | csx/
154 | *.build.csdef
155 |
156 | # Windows Store app package directory
157 | AppPackages/
158 |
159 | # Visual Studio cache files
160 | # files ending in .cache can be ignored
161 | *.[Cc]ache
162 | # but keep track of directories ending in .cache
163 | !*.[Cc]ache/
164 |
165 | # Others
166 | ClientBin/
167 | [Ss]tyle[Cc]op.*
168 | ~$*
169 | *~
170 | *.dbmdl
171 | *.dbproj.schemaview
172 | *.pfx
173 | *.publishsettings
174 | node_modules/
175 | orleans.codegen.cs
176 |
177 | # RIA/Silverlight projects
178 | Generated_Code/
179 |
180 | # Backup & report files from converting an old project file
181 | # to a newer Visual Studio version. Backup files are not needed,
182 | # because we have git ;-)
183 | _UpgradeReport_Files/
184 | Backup*/
185 | UpgradeLog*.XML
186 | UpgradeLog*.htm
187 |
188 | # SQL Server files
189 | *.mdf
190 | *.ldf
191 |
192 | # Business Intelligence projects
193 | *.rdl.data
194 | *.bim.layout
195 | *.bim_*.settings
196 |
197 | # Microsoft Fakes
198 | FakesAssemblies/
199 |
200 | # Node.js Tools for Visual Studio
201 | .ntvs_analysis.dat
202 |
203 | # Visual Studio 6 build log
204 | *.plg
205 |
206 | # Visual Studio 6 workspace options file
207 | *.opt
208 |
209 | # LightSwitch generated files
210 | GeneratedArtifacts/
211 | _Pvt_Extensions/
212 | ModelManifest.xml
213 |
--------------------------------------------------------------------------------
/CortanaService/CortanaService.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {480969FC-1CBC-490D-B741-79D79C96B838}
8 | winmdobj
9 | Properties
10 | CortanaService
11 | CortanaService
12 | en-US
13 | UAP
14 | 10.0.14393.0
15 | 10.0.14393.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | false
20 |
21 |
22 | AnyCPU
23 | true
24 | full
25 | false
26 | bin\Debug\
27 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
28 | prompt
29 | 4
30 |
31 |
32 | AnyCPU
33 | pdbonly
34 | true
35 | bin\Release\
36 | TRACE;NETFX_CORE;WINDOWS_UWP
37 | prompt
38 | 4
39 |
40 |
41 | x86
42 | true
43 | bin\x86\Debug\
44 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
45 | ;2008
46 | full
47 | x86
48 | false
49 | prompt
50 |
51 |
52 | x86
53 | bin\x86\Release\
54 | TRACE;NETFX_CORE;WINDOWS_UWP
55 | true
56 | ;2008
57 | pdbonly
58 | x86
59 | false
60 | prompt
61 |
62 |
63 | ARM
64 | true
65 | bin\ARM\Debug\
66 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
67 | ;2008
68 | full
69 | ARM
70 | false
71 | prompt
72 |
73 |
74 | ARM
75 | bin\ARM\Release\
76 | TRACE;NETFX_CORE;WINDOWS_UWP
77 | true
78 | ;2008
79 | pdbonly
80 | ARM
81 | false
82 | prompt
83 |
84 |
85 | x64
86 | true
87 | bin\x64\Debug\
88 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
89 | ;2008
90 | full
91 | x64
92 | false
93 | prompt
94 |
95 |
96 | x64
97 | bin\x64\Release\
98 | TRACE;NETFX_CORE;WINDOWS_UWP
99 | true
100 | ;2008
101 | pdbonly
102 | x64
103 | false
104 | prompt
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 | 14.0
116 |
117 |
118 |
125 |
--------------------------------------------------------------------------------
/CortanaService/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("CortanaService")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("CortanaService")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/CortanaService/Service.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using Windows.ApplicationModel.AppService;
5 | using Windows.ApplicationModel.Background;
6 | using Windows.ApplicationModel.VoiceCommands;
7 | using Windows.UI.Xaml.Media.Imaging;
8 |
9 | namespace CortanaService
10 | {
11 | public sealed class Service : XamlRenderingBackgroundTask
12 | {
13 | private BackgroundTaskDeferral serviceDeferral;
14 | VoiceCommandServiceConnection voiceServiceConnection;
15 |
16 | protected override async void OnRun(IBackgroundTaskInstance taskInstance)
17 | {
18 | this.serviceDeferral = taskInstance.GetDeferral();
19 | taskInstance.Canceled += OnTaskCanceled;
20 |
21 | var triggerDetails = taskInstance.TriggerDetails as AppServiceTriggerDetails;
22 |
23 | VoiceCommandResponse response;
24 | try
25 | {
26 | voiceServiceConnection = VoiceCommandServiceConnection.FromAppServiceTriggerDetails(triggerDetails);
27 | voiceServiceConnection.VoiceCommandCompleted += VoiceCommandCompleted;
28 | VoiceCommand voiceCommand = await voiceServiceConnection.GetVoiceCommandAsync();
29 |
30 | switch (voiceCommand.CommandName)
31 | {
32 |
33 | case "sendMessageInCanvas":
34 |
35 | var responseMessage = new VoiceCommandUserMessage();
36 | responseMessage.DisplayMessage = responseMessage.SpokenMessage = "Testing Cortana App Service";
37 |
38 | response = VoiceCommandResponse.CreateResponse(responseMessage);
39 | await voiceServiceConnection.ReportSuccessAsync(response);
40 |
41 | break;
42 |
43 | }
44 | }
45 | catch (Exception ex)
46 | {
47 | Debug.WriteLine(ex.Message);
48 | }
49 | finally
50 | {
51 | if (this.serviceDeferral != null)
52 | {
53 | //Complete the service deferral
54 | this.serviceDeferral.Complete();
55 | }
56 | }
57 |
58 | }
59 |
60 | private void VoiceCommandCompleted(VoiceCommandServiceConnection sender,
61 | VoiceCommandCompletedEventArgs args)
62 | {
63 | if (this.serviceDeferral != null)
64 | {
65 | this.serviceDeferral.Complete();
66 | }
67 | }
68 |
69 | private void OnTaskCanceled(IBackgroundTaskInstance sender,
70 | BackgroundTaskCancellationReason reason)
71 | {
72 | if (this.serviceDeferral != null)
73 | {
74 | this.serviceDeferral.Complete();
75 | }
76 | }
77 | }
78 |
79 | }
--------------------------------------------------------------------------------
/CortanaService/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
4 | },
5 | "frameworks": {
6 | "uap10.0": {}
7 | },
8 | "runtimes": {
9 | "win10-arm": {},
10 | "win10-arm-aot": {},
11 | "win10-x86": {},
12 | "win10-x86-aot": {},
13 | "win10-x64": {},
14 | "win10-x64-aot": {}
15 | }
16 | }
--------------------------------------------------------------------------------
/ExtensibilitySample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.24720.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensibilitySample", "ExtensibilitySample\ExtensibilitySample.csproj", "{1D5E07CA-CF4D-49B8-8672-46618FC02306}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CortanaService", "CortanaService\CortanaService.csproj", "{480969FC-1CBC-490D-B741-79D79C96B838}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Debug|ARM = Debug|ARM
14 | Debug|x64 = Debug|x64
15 | Debug|x86 = Debug|x86
16 | Release|Any CPU = Release|Any CPU
17 | Release|ARM = Release|ARM
18 | Release|x64 = Release|x64
19 | Release|x86 = Release|x86
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Debug|Any CPU.ActiveCfg = Debug|x86
23 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Debug|ARM.ActiveCfg = Debug|ARM
24 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Debug|ARM.Build.0 = Debug|ARM
25 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Debug|ARM.Deploy.0 = Debug|ARM
26 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Debug|x64.ActiveCfg = Debug|x64
27 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Debug|x64.Build.0 = Debug|x64
28 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Debug|x64.Deploy.0 = Debug|x64
29 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Debug|x86.ActiveCfg = Debug|x86
30 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Debug|x86.Build.0 = Debug|x86
31 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Debug|x86.Deploy.0 = Debug|x86
32 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Release|Any CPU.ActiveCfg = Release|x86
33 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Release|ARM.ActiveCfg = Release|ARM
34 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Release|ARM.Build.0 = Release|ARM
35 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Release|ARM.Deploy.0 = Release|ARM
36 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Release|x64.ActiveCfg = Release|x64
37 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Release|x64.Build.0 = Release|x64
38 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Release|x64.Deploy.0 = Release|x64
39 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Release|x86.ActiveCfg = Release|x86
40 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Release|x86.Build.0 = Release|x86
41 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}.Release|x86.Deploy.0 = Release|x86
42 | {480969FC-1CBC-490D-B741-79D79C96B838}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {480969FC-1CBC-490D-B741-79D79C96B838}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {480969FC-1CBC-490D-B741-79D79C96B838}.Debug|ARM.ActiveCfg = Debug|ARM
45 | {480969FC-1CBC-490D-B741-79D79C96B838}.Debug|ARM.Build.0 = Debug|ARM
46 | {480969FC-1CBC-490D-B741-79D79C96B838}.Debug|x64.ActiveCfg = Debug|x64
47 | {480969FC-1CBC-490D-B741-79D79C96B838}.Debug|x64.Build.0 = Debug|x64
48 | {480969FC-1CBC-490D-B741-79D79C96B838}.Debug|x86.ActiveCfg = Debug|x86
49 | {480969FC-1CBC-490D-B741-79D79C96B838}.Debug|x86.Build.0 = Debug|x86
50 | {480969FC-1CBC-490D-B741-79D79C96B838}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {480969FC-1CBC-490D-B741-79D79C96B838}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {480969FC-1CBC-490D-B741-79D79C96B838}.Release|ARM.ActiveCfg = Release|ARM
53 | {480969FC-1CBC-490D-B741-79D79C96B838}.Release|ARM.Build.0 = Release|ARM
54 | {480969FC-1CBC-490D-B741-79D79C96B838}.Release|x64.ActiveCfg = Release|x64
55 | {480969FC-1CBC-490D-B741-79D79C96B838}.Release|x64.Build.0 = Release|x64
56 | {480969FC-1CBC-490D-B741-79D79C96B838}.Release|x86.ActiveCfg = Release|x86
57 | {480969FC-1CBC-490D-B741-79D79C96B838}.Release|x86.Build.0 = Release|x86
58 | EndGlobalSection
59 | GlobalSection(SolutionProperties) = preSolution
60 | HideSolutionNode = FALSE
61 | EndGlobalSection
62 | EndGlobal
63 |
--------------------------------------------------------------------------------
/ExtensibilitySample/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/ExtensibilitySample/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.ApplicationModel;
7 | using Windows.ApplicationModel.Activation;
8 | using Windows.Foundation;
9 | using Windows.Foundation.Collections;
10 | using Windows.Storage;
11 | using Windows.UI.Xaml;
12 | using Windows.UI.Xaml.Controls;
13 | using Windows.UI.Xaml.Controls.Primitives;
14 | using Windows.UI.Xaml.Data;
15 | using Windows.UI.Xaml.Input;
16 | using Windows.UI.Xaml.Media;
17 | using Windows.UI.Xaml.Media.Imaging;
18 | using Windows.UI.Xaml.Navigation;
19 |
20 | namespace ExtensibilitySample
21 | {
22 |
23 | public static class AppData
24 | {
25 | // create extensions list
26 | private static ExtensionManager extensionManager = new ExtensionManager("build2016.appextensibility.demo");
27 |
28 | // create the current editing image
29 | public static WriteableBitmap currentImage = new WriteableBitmap(1, 1);
30 | public static string currentImageString = null;
31 |
32 | internal static ExtensionManager ExtensionManager
33 | {
34 | get
35 | {
36 | return extensionManager;
37 | }
38 |
39 | set
40 | {
41 | extensionManager = value;
42 | }
43 | }
44 | }
45 |
46 | ///
47 | /// Provides application-specific behavior to supplement the default Application class.
48 | ///
49 | sealed partial class App : Application
50 | {
51 | ///
52 | /// Initializes the singleton application object. This is the first line of authored code
53 | /// executed, and as such is the logical equivalent of main() or WinMain().
54 | ///
55 | public App()
56 | {
57 | Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
58 | Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
59 | Microsoft.ApplicationInsights.WindowsCollectors.Session);
60 | this.InitializeComponent();
61 | this.Suspending += OnSuspending;
62 | }
63 |
64 | ///
65 | /// Invoked when the application is launched normally by the end user. Other entry points
66 | /// will be used such as when the application is launched to open a specific file.
67 | ///
68 | /// Details about the launch request and process.
69 | protected async override void OnLaunched(LaunchActivatedEventArgs e)
70 | {
71 |
72 |
73 | #if DEBUG
74 | if (System.Diagnostics.Debugger.IsAttached)
75 | {
76 | this.DebugSettings.EnableFrameRateCounter = true;
77 | }
78 | #endif
79 |
80 | try
81 | {
82 | // Install the VCD.
83 | StorageFile vcdStorageFile =
84 | await Package.Current.InstalledLocation.GetFileAsync(
85 | @"ExtensibilitySampleCommands.xml");
86 |
87 | await
88 | Windows.ApplicationModel.VoiceCommands.VoiceCommandDefinitionManager.
89 | InstallCommandDefinitionsFromStorageFileAsync(vcdStorageFile);
90 | }
91 | catch (Exception ex)
92 | {
93 | System.Diagnostics.Debug.WriteLine(
94 | "Installing Voice Commands Failed: " + ex.ToString());
95 | }
96 |
97 | Frame rootFrame = Window.Current.Content as Frame;
98 |
99 | // Do not repeat app initialization when the Window already has content,
100 | // just ensure that the window is active
101 | if (rootFrame == null)
102 | {
103 | // Create a Frame to act as the navigation context and navigate to the first page
104 | rootFrame = new Frame();
105 |
106 | rootFrame.NavigationFailed += OnNavigationFailed;
107 |
108 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
109 | {
110 | //TODO: Load state from previously suspended application
111 | }
112 |
113 | // Place the frame in the current Window
114 | Window.Current.Content = rootFrame;
115 | }
116 |
117 | if (rootFrame.Content == null)
118 | {
119 | // When the navigation stack isn't restored navigate to the first page,
120 | // configuring the new page by passing required information as a navigation
121 | // parameter
122 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
123 | }
124 | // Ensure the current window is active
125 | Window.Current.Activate();
126 | }
127 |
128 | ///
129 | /// Invoked when Navigation to a certain page fails
130 | ///
131 | /// The Frame which failed navigation
132 | /// Details about the navigation failure
133 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
134 | {
135 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
136 | }
137 |
138 | ///
139 | /// Invoked when application execution is being suspended. Application state is saved
140 | /// without knowing whether the application will be terminated or resumed with the contents
141 | /// of memory still intact.
142 | ///
143 | /// The source of the suspend request.
144 | /// Details about the suspend request.
145 | private void OnSuspending(object sender, SuspendingEventArgs e)
146 | {
147 | var deferral = e.SuspendingOperation.GetDeferral();
148 | //TODO: Save application state and stop any background activity
149 | deferral.Complete();
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/ExtensibilitySample/ApplicationInsights.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/BadgeLogo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/BadgeLogo.scale-100.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/BadgeLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/BadgeLogo.scale-200.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/BadgeLogo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/BadgeLogo.scale-400.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/Square150x150Logo.scale-100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/Square150x150Logo.scale-100.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/Square150x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/Square150x150Logo.scale-400.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/Square44x44Logo.targetsize-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/Square44x44Logo.targetsize-48.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/ExtensibilitySample/Assets/Wide310x150Logo.scale-400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/App-Extensibility-Sample/de344726d28bd75bc8cf3fd34099d093d8a6bc3e/ExtensibilitySample/Assets/Wide310x150Logo.scale-400.png
--------------------------------------------------------------------------------
/ExtensibilitySample/EditorTab.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
88 |
89 |
94 |
95 |
102 |
103 |
104 |
107 |
108 |
109 |
110 |
111 |
116 |
117 |
118 |
119 |
120 |
127 |
129 |
130 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/ExtensibilitySample/EditorTab.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Threading.Tasks;
4 | using Windows.ApplicationModel.DataTransfer;
5 | using Windows.Foundation.Collections;
6 | using Windows.Storage;
7 | using Windows.Storage.Pickers;
8 | using Windows.System;
9 | using Windows.UI.Popups;
10 | using Windows.UI.Xaml;
11 | using Windows.UI.Xaml.Controls;
12 | using Windows.UI.Xaml.Navigation;
13 | using Windows.ApplicationModel.AppService;
14 | using Windows.UI.Xaml.Media.Imaging;
15 |
16 | // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
17 |
18 | namespace ExtensibilitySample
19 | {
20 | ///
21 | /// An empty page that can be used on its own or navigated to within a Frame.
22 | ///
23 | public sealed partial class EditorTab : Page
24 | {
25 | public EditorTab()
26 | {
27 |
28 | //this.commands.Width = this.ActualWidth;
29 | this.InitializeComponent();
30 | //DataContext = AppData.currentImage;
31 | DataContext = AppData.ExtensionManager.Extensions;
32 | }
33 |
34 | protected override void OnNavigatedTo(NavigationEventArgs e)
35 | {
36 | base.OnNavigatedTo(e);
37 | }
38 |
39 |
40 | // run an extension button
41 | private void Run_Click(object sender, RoutedEventArgs e)
42 | {
43 |
44 | // test the extension
45 | Button btn = sender as Button;
46 | Extension ext = btn.DataContext as Extension;
47 |
48 | if (AppData.currentImageString != null)
49 | {
50 | ext.InvokeLoad(ImageTools.AddDataURIHeader(AppData.currentImageString));
51 | }
52 | }
53 |
54 | // open image button
55 | private async void Open_Click(object sender, RoutedEventArgs e)
56 | {
57 | // open file
58 | FileOpenPicker open = new FileOpenPicker();
59 | open.FileTypeFilter.Add(".jpg");
60 | open.FileTypeFilter.Add(".png");
61 | open.FileTypeFilter.Add(".jpeg");
62 | open.ViewMode = PickerViewMode.Thumbnail;
63 | open.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
64 | open.CommitButtonText = "Open";
65 |
66 | // Open a stream for the selected file
67 | StorageFile file = await open.PickSingleFileAsync();
68 |
69 | // load the file as the image
70 | if (file != null)
71 | {
72 | try
73 | {
74 | string imgstr = await ImageTools.FileToString(file);
75 | if (imgstr != null)
76 | {
77 | await AppData.currentImage.SetSourceAsync(ImageTools.DecodeStringToBitmapSource(imgstr));
78 | AppData.currentImageString = imgstr;
79 | }
80 | }
81 | catch
82 | {
83 | MessageDialog md = new MessageDialog("Error loading image file.");
84 | await md.ShowAsync();
85 | }
86 | }
87 | }
88 |
89 | private void Save_Click(object sender, RoutedEventArgs e)
90 | {
91 |
92 | }
93 |
94 | private async void Grayscale_Click(object sender, RoutedEventArgs e)
95 | {
96 | using (var connection = new AppServiceConnection())
97 | {
98 | connection.AppServiceName = "com.microsoft.grayscaleservice";
99 | connection.PackageFamilyName = "AppExtensibility.Extension.Grayscale_byq669axdz8jy";
100 |
101 | AppServiceConnectionStatus status = await connection.OpenAsync();
102 | if (status == AppServiceConnectionStatus.Success)
103 | {
104 | #region SendMessage
105 | // send request to service
106 | var request = new ValueSet();
107 | request.Add("Command", "Grayscale");
108 | request.Add("Pixels", ImageTools.GetBitmapBytes(AppData.currentImage));
109 | request.Add("Height", AppData.currentImage.PixelHeight);
110 | request.Add("Width", AppData.currentImage.PixelWidth);
111 |
112 | // get response
113 | AppServiceResponse response = await connection.SendMessageAsync(request);
114 |
115 | if (response.Status == AppServiceResponseStatus.Success)
116 | #endregion
117 | #region HandleMessage
118 | {
119 | #region ErrorHandling
120 | // convert imagestring back
121 | ValueSet message = response.Message as ValueSet;
122 | if (message.ContainsKey("Pixels") &&
123 | message.ContainsKey("Height") &&
124 | message.ContainsKey("Width"))
125 | {
126 | #endregion
127 | byte[] pixels = message["Pixels"] as byte[];
128 | int height = (int)message["Height"];
129 | int width = (int)message["Width"];
130 |
131 | // encode the bytes to a string, and then the image.
132 | string encodedImage = await ImageTools.EncodeBytesToPNGString(pixels, (uint)width, (uint)height);
133 | await AppData.currentImage.SetSourceAsync(ImageTools.DecodeStringToBitmapSource(encodedImage));
134 | AppData.currentImageString = encodedImage;
135 | }
136 | }
137 | #endregion
138 |
139 | }
140 | }
141 | }
142 |
143 | private async void Crop_Click(object sender, RoutedEventArgs e)
144 | {
145 | #region File Setup
146 | // Load a File Picker that shows image file types
147 | FileOpenPicker open = new FileOpenPicker();
148 | open.FileTypeFilter.Add(".jpg");
149 | open.FileTypeFilter.Add(".png");
150 | open.FileTypeFilter.Add(".jpeg");
151 | open.ViewMode = PickerViewMode.Thumbnail;
152 | open.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
153 | open.CommitButtonText = "Open";
154 |
155 | // Wait for user to select a file
156 | StorageFile source = await open.PickSingleFileAsync();
157 |
158 | // Verify the source is not null
159 | if (source != null)
160 | {
161 | try
162 | {
163 | // Create a destination file
164 | StorageFile dest = await KnownFolders.PicturesLibrary.CreateFileAsync("Cropped.jpg", CreationCollisionOption.ReplaceExisting);
165 |
166 | #endregion
167 |
168 | // Call CropImageAsync and receive Result
169 | LaunchUriResult result = await this.CropImageAsync(source, dest, 500, 500);
170 |
171 | // Load Destination Image into Image Preview
172 | var stream = await dest.OpenReadAsync();
173 | await AppData.currentImage.SetSourceAsync(stream);
174 |
175 | #region Error Handling
176 | // Verify result and load picture into the source
177 | if (result.Status == LaunchUriStatus.Success && result.Result != null)
178 | {
179 | string imgstr = await ImageTools.FileToString(dest);
180 | if (imgstr != null)
181 | {
182 |
183 | await AppData.currentImage.SetSourceAsync(ImageTools.DecodeStringToBitmapSource(imgstr));
184 | AppData.currentImageString = imgstr;
185 | }
186 | }
187 |
188 | }
189 | catch
190 | {
191 | MessageDialog md = new MessageDialog("Error loading image file.");
192 | await md.ShowAsync();
193 | }
194 |
195 | }
196 | #endregion
197 | }
198 |
199 | private async Task CropImageAsync(IStorageFile input, IStorageFile destination, int width, int height)
200 | {
201 | // Get access tokens to pass input and output files between apps
202 | var inputToken = SharedStorageAccessManager.AddFile(input);
203 | var destinationToken = SharedStorageAccessManager.AddFile(destination);
204 |
205 | // Specify an app to launch by using LaunchUriForResultsAsync
206 | var options = new LauncherOptions();
207 | options.TargetApplicationPackageFamilyName = "Microsoft.Windows.Photos_8wekyb3d8bbwe";
208 |
209 | // Specify protocol launch options
210 | var parameters = new ValueSet();
211 | parameters.Add("InputToken", inputToken);
212 | parameters.Add("DestinationToken", destinationToken);
213 | parameters.Add("CropWidthPixels", 500);
214 | parameters.Add("CropHeightPixels", 500);
215 | parameters.Add("EllipticalCrop", false);
216 |
217 | // Perform LaunchUriForResultsAsync
218 | return await Launcher.LaunchUriForResultsAsync(new Uri("microsoft.windows.photos.crop:"), options, parameters);
219 | }
220 |
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/ExtensibilitySample/ExtensibilitySample.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {1D5E07CA-CF4D-49B8-8672-46618FC02306}
8 | AppContainerExe
9 | Properties
10 | ExtensibilitySample
11 | ExtensibilitySample
12 | en-US
13 | UAP
14 | 10.0.14393.0
15 | 10.0.14393.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | ExtensibilitySample_TemporaryKey.pfx
20 | True
21 | False
22 | Never
23 | 61AED3F4FECFF74E81779ED0FCF7A45F848344A2
24 |
25 |
26 | true
27 | bin\x86\Debug\
28 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
29 | ;2008
30 | full
31 | x86
32 | false
33 | prompt
34 | true
35 |
36 |
37 | bin\x86\Release\
38 | TRACE;NETFX_CORE;WINDOWS_UWP
39 | true
40 | ;2008
41 | pdbonly
42 | x86
43 | false
44 | prompt
45 | true
46 | true
47 |
48 |
49 | true
50 | bin\ARM\Debug\
51 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
52 | ;2008
53 | full
54 | ARM
55 | false
56 | prompt
57 | true
58 |
59 |
60 | bin\ARM\Release\
61 | TRACE;NETFX_CORE;WINDOWS_UWP
62 | true
63 | ;2008
64 | pdbonly
65 | ARM
66 | false
67 | prompt
68 | true
69 | true
70 |
71 |
72 | true
73 | bin\x64\Debug\
74 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
75 | ;2008
76 | full
77 | x64
78 | false
79 | prompt
80 | true
81 |
82 |
83 | bin\x64\Release\
84 | TRACE;NETFX_CORE;WINDOWS_UWP
85 | true
86 | ;2008
87 | pdbonly
88 | x64
89 | false
90 | prompt
91 | true
92 | true
93 |
94 |
95 |
96 |
97 | PreserveNewest
98 |
99 |
100 |
101 |
102 |
103 | App.xaml
104 |
105 |
106 | EditorTab.xaml
107 |
108 |
109 |
110 | ExtensionsTab.xaml
111 |
112 |
113 | Image.xaml
114 |
115 |
116 |
117 | MainPage.xaml
118 |
119 |
120 |
121 |
122 |
123 |
124 | Designer
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 | Designer
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | MSBuild:Compile
151 | Designer
152 |
153 |
154 | Designer
155 | MSBuild:Compile
156 |
157 |
158 | Designer
159 | MSBuild:Compile
160 |
161 |
162 | Designer
163 | MSBuild:Compile
164 |
165 |
166 | MSBuild:Compile
167 | Designer
168 |
169 |
170 | Designer
171 | MSBuild:Compile
172 |
173 |
174 |
175 |
176 | {480969fc-1cbc-490d-b741-79d79c96b838}
177 | CortanaService
178 |
179 |
180 |
181 | 14.0
182 |
183 |
184 |
191 |
--------------------------------------------------------------------------------
/ExtensibilitySample/ExtensibilitySampleCommands.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Build Sample
5 | Build Sample what can your app service do?
6 |
7 |
8 | Build Sample what can your app service do?
9 | What can your app service do
10 |
11 |
12 |
13 |
14 | Build Sample show me my cropped picture
15 | Show me my cropped picture
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ExtensibilitySample/ExtensionManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.ComponentModel;
5 | using System.Diagnostics;
6 | using System.Linq;
7 | using System.Threading.Tasks;
8 | using Windows.ApplicationModel;
9 | using Windows.ApplicationModel.AppExtensions; // App Extensions!!
10 | using Windows.ApplicationModel.AppService;
11 | using Windows.Foundation.Collections;
12 | using Windows.Storage;
13 | using Windows.UI.Core;
14 | using Windows.UI.Popups;
15 | using Windows.UI.Xaml;
16 | using Windows.UI.Xaml.Controls;
17 | using Windows.UI.Xaml.Media.Imaging;
18 |
19 | namespace ExtensibilitySample
20 | {
21 | class ExtensionManager
22 | {
23 | private ObservableCollection _extensions;
24 | private string _contract;
25 | private CoreDispatcher _dispatcher;
26 | private AppExtensionCatalog _catalog;
27 |
28 | public ExtensionManager(string contract)
29 | {
30 | // extensions list
31 | _extensions = new ObservableCollection();
32 |
33 | // catalog & contract
34 | _contract = contract;
35 | _catalog = AppExtensionCatalog.Open(_contract);
36 |
37 | // using a method that uses the UI Dispatcher before initializing will throw an exception
38 | _dispatcher = null;
39 | }
40 |
41 | public ObservableCollection Extensions
42 | {
43 | get { return _extensions; }
44 | }
45 |
46 | public string Contract
47 | {
48 | get { return _contract; }
49 | }
50 |
51 | // this sets up UI dispatcher and does initial extension scan
52 | public void Initialize()
53 | {
54 | #region Error Checking & Dispatcher Setup
55 | // check that we haven't already been initialized
56 | if (_dispatcher != null)
57 | {
58 | throw new ExtensionManagerException("Extension Manager for " + this.Contract + " is already initialized.");
59 | }
60 |
61 | // thread that initializes the extension manager has the dispatcher
62 | _dispatcher = Windows.UI.Core.CoreWindow.GetForCurrentThread().Dispatcher;
63 | #endregion
64 |
65 | // set up extension management events
66 | _catalog.PackageInstalled += Catalog_PackageInstalled;
67 | _catalog.PackageUpdated += Catalog_PackageUpdated;
68 | _catalog.PackageUninstalling += Catalog_PackageUninstalling;
69 | _catalog.PackageUpdating += Catalog_PackageUpdating;
70 | _catalog.PackageStatusChanged += Catalog_PackageStatusChanged;
71 |
72 | // Scan all extensions
73 | FindAllExtensions();
74 | }
75 |
76 | public async void FindAllExtensions()
77 | {
78 | #region Error Checking
79 | // make sure we have initialized
80 | if (_dispatcher == null)
81 | {
82 | throw new ExtensionManagerException("Extension Manager for " + this.Contract + " is not initialized.");
83 | }
84 | #endregion
85 |
86 | // load all the extensions currently installed
87 | IReadOnlyList extensions = await _catalog.FindAllAsync();
88 | foreach (AppExtension ext in extensions)
89 | {
90 | // load this extension
91 | await LoadExtension(ext);
92 | }
93 | }
94 |
95 | private async void Catalog_PackageInstalled(AppExtensionCatalog sender, AppExtensionPackageInstalledEventArgs args)
96 | {
97 | await _dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => {
98 | foreach (AppExtension ext in args.Extensions)
99 | {
100 | await LoadExtension(ext);
101 | }
102 | });
103 | }
104 |
105 | // package has been updated, so reload the extensions
106 | private async void Catalog_PackageUpdated(AppExtensionCatalog sender, AppExtensionPackageUpdatedEventArgs args)
107 | {
108 | await _dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => {
109 | foreach (AppExtension ext in args.Extensions)
110 | {
111 | await LoadExtension(ext);
112 | }
113 | });
114 | }
115 |
116 | // package is updating, so just unload the extensions
117 | private async void Catalog_PackageUpdating(AppExtensionCatalog sender, AppExtensionPackageUpdatingEventArgs args)
118 | {
119 | await UnloadExtensions(args.Package);
120 | }
121 |
122 | // package is removed, so unload all the extensions in the package and remove it
123 | private async void Catalog_PackageUninstalling(AppExtensionCatalog sender, AppExtensionPackageUninstallingEventArgs args)
124 | {
125 | await RemoveExtensions(args.Package);
126 | }
127 |
128 | // package status has changed, could be invalid, licensing issue, app was on USB and removed, etc
129 | private async void Catalog_PackageStatusChanged(AppExtensionCatalog sender, AppExtensionPackageStatusChangedEventArgs args)
130 | {
131 | // get package status
132 | if (!(args.Package.Status.VerifyIsOK()))
133 | {
134 | // if it's offline unload only
135 | if (args.Package.Status.PackageOffline)
136 | {
137 | await UnloadExtensions(args.Package);
138 | }
139 |
140 | // package is being serviced or deployed
141 | else if (args.Package.Status.Servicing || args.Package.Status.DeploymentInProgress)
142 | {
143 | // ignore these package status events
144 | }
145 |
146 | // package is tampered or invalid or some other issue
147 | // glyphing the extensions would be a good user experience
148 | else
149 | {
150 | await RemoveExtensions(args.Package);
151 | }
152 |
153 | }
154 | // if package is now OK, attempt to load the extensions
155 | else
156 | {
157 | // try to load any extensions associated with this package
158 | await LoadExtensions(args.Package);
159 | }
160 | }
161 |
162 | // loads an extension
163 | public async Task LoadExtension(AppExtension ext)
164 | {
165 | // get unique identifier for this extension
166 | string identifier = ext.AppInfo.AppUserModelId + "!" + ext.Id;
167 |
168 | // load the extension if the package is OK
169 | if (!(ext.Package.Status.VerifyIsOK()
170 | // This is where we'd normally do signature verfication, but for demo purposes it isn't important
171 | // Below is an example of how you'd ensure that you only load store-signed extensions :)
172 | //&& ext.Package.SignatureKind == PackageSignatureKind.Store
173 | ))
174 | {
175 | // if this package doesn't meet our requirements
176 | // ignore it and return
177 | return;
178 | }
179 |
180 | // if its already existing then this is an update
181 | Extension existingExt = _extensions.Where(e => e.UniqueId == identifier).FirstOrDefault();
182 |
183 | // new extension
184 | if (existingExt == null)
185 | {
186 | // get extension properties
187 | var properties = await ext.GetExtensionPropertiesAsync() as PropertySet;
188 |
189 | // get logo
190 | var filestream = await (ext.AppInfo.DisplayInfo.GetLogo(new Windows.Foundation.Size(1, 1))).OpenReadAsync();
191 | BitmapImage logo = new BitmapImage();
192 | logo.SetSource(filestream);
193 |
194 | // create new extension
195 | Extension nExt = new Extension(ext, properties, logo);
196 |
197 | // Add it to extension list
198 | _extensions.Add(nExt);
199 |
200 | // load it
201 | await nExt.Load();
202 | }
203 | // update
204 | else
205 | {
206 | // unload the extension
207 | existingExt.Unload();
208 |
209 | // update the extension
210 | await existingExt.Update(ext);
211 | }
212 | }
213 |
214 | // loads all extensions associated with a package - used for when package status comes back
215 | public async Task LoadExtensions(Package package)
216 | {
217 | await _dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
218 | _extensions.Where(ext => ext.AppExtension.Package.Id.FamilyName == package.Id.FamilyName).ToList().ForEach(async e => { await e.Load(); });
219 | });
220 | }
221 |
222 | // unloads all extensions associated with a package - used for updating and when package status goes away
223 | public async Task UnloadExtensions(Package package)
224 | {
225 | await _dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
226 | _extensions.Where(ext => ext.AppExtension.Package.Id.FamilyName == package.Id.FamilyName).ToList().ForEach(e => { e.Unload(); });
227 | });
228 | }
229 |
230 | // removes all extensions associated with a package - used when removing a package or it becomes invalid
231 | public async Task RemoveExtensions(Package package)
232 | {
233 | await _dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => {
234 | _extensions.Where(ext => ext.AppExtension.Package.Id.FamilyName == package.Id.FamilyName).ToList().ForEach(e => { e.Unload(); _extensions.Remove(e); });
235 | });
236 | }
237 |
238 |
239 | public async void RemoveExtension(Extension ext)
240 | {
241 | await _catalog.RequestRemovePackageAsync(ext.AppExtension.Package.Id.FullName);
242 | }
243 |
244 | #region Extra exceptions
245 | // For exceptions using the Extension Manager
246 | public class ExtensionManagerException : Exception
247 | {
248 | public ExtensionManagerException() { }
249 |
250 | public ExtensionManagerException(string message) : base(message) { }
251 |
252 | public ExtensionManagerException(string message, Exception inner) : base(message, inner) { }
253 | }
254 | #endregion
255 | }
256 |
257 | public class Extension : INotifyPropertyChanged
258 | {
259 | #region Member Vars
260 | private AppExtension _extension;
261 | private PropertySet _properties;
262 | private bool _enabled;
263 | private bool _loaded;
264 | private bool _offline;
265 | private string _serviceName;
266 | private string _uniqueId;
267 | private WebView _extwebview;
268 | private BitmapImage _logo;
269 | private Visibility _visibility;
270 |
271 | private readonly object _sync = new object();
272 |
273 | public event PropertyChangedEventHandler PropertyChanged;
274 | #endregion
275 |
276 | public Extension(AppExtension ext, PropertySet properties, BitmapImage logo)
277 | {
278 | _extension = ext;
279 | _properties = properties;
280 | _enabled = false;
281 | _loaded = false;
282 | _offline = false;
283 | _logo = logo;
284 | _visibility = Visibility.Collapsed;
285 | _extwebview = new WebView();
286 |
287 | #region Properties
288 | _serviceName = null;
289 | if (_properties != null)
290 | {
291 | if (_properties.ContainsKey("Service"))
292 | {
293 | PropertySet serviceProperty = _properties["Service"] as PropertySet;
294 | _serviceName = serviceProperty["#text"].ToString();
295 | }
296 | }
297 | #endregion
298 |
299 | //AUMID + Extension ID is the unique identifier for an extension
300 | _uniqueId = ext.AppInfo.AppUserModelId + "!" + ext.Id;
301 |
302 | // webview event when the extension notifies us that something happened
303 | _extwebview.ScriptNotify += ExtensionCallback;
304 | }
305 |
306 | #region Properties
307 | public BitmapImage Logo
308 | {
309 | get { return _logo; }
310 | }
311 |
312 | public string UniqueId
313 | {
314 | get { return _uniqueId; }
315 | }
316 |
317 | public bool Enabled
318 | {
319 | get { return _enabled; }
320 | }
321 |
322 | public WebView ExtensionWebView
323 | {
324 | get { return _extwebview; }
325 | }
326 |
327 | public bool Offline
328 | {
329 | get { return _offline; }
330 | }
331 |
332 | public AppExtension AppExtension
333 | {
334 | get { return _extension; }
335 | }
336 |
337 | public Visibility Visible
338 | {
339 | get { return _visibility; }
340 | }
341 | #endregion
342 |
343 | // this calls the 'extensionLoad' function in the script file, if it exists.
344 | public async void InvokeLoad(string str)
345 | {
346 | if (this._loaded)
347 | {
348 | if (_serviceName == null)
349 | {
350 | try
351 | {
352 | // this is dangerous!
353 | await _extwebview.InvokeScriptAsync("extensionLoad", new string[] { str });
354 | }
355 | catch (Exception e)
356 | {
357 | // show errors
358 | return;
359 | }
360 | }
361 | #region App Service
362 | // App services are a better approach!
363 | else
364 | {
365 | try
366 | {
367 | // do app service call
368 | using (var connection = new AppServiceConnection())
369 | {
370 | // service name was in properties
371 | connection.AppServiceName = _serviceName;
372 |
373 | // package Family Name is in the extension
374 | connection.PackageFamilyName = _extension.Package.Id.FamilyName;
375 |
376 | // open connection
377 | AppServiceConnectionStatus status = await connection.OpenAsync();
378 | if (status != AppServiceConnectionStatus.Success)
379 | {
380 | Debug.WriteLine("Failed App Service Connection");
381 | }
382 | else
383 | {
384 | // send request to service
385 | var request = new ValueSet();
386 | request.Add("Command", "Load");
387 | request.Add("Pixels", ImageTools.GetBitmapBytes(AppData.currentImage));
388 | request.Add("Height", AppData.currentImage.PixelHeight);
389 | request.Add("Width", AppData.currentImage.PixelWidth);
390 |
391 | // get response
392 | AppServiceResponse response = await connection.SendMessageAsync(request);
393 | if (response.Status == AppServiceResponseStatus.Success)
394 | {
395 | ValueSet message = response.Message as ValueSet;
396 | if (message.ContainsKey("Pixels") &&
397 | message.ContainsKey("Height") &&
398 | message.ContainsKey("Width"))
399 | {
400 | byte[] pixels = message["Pixels"] as byte[];
401 | int height = (int) message["Height"];
402 | int width = (int) message["Width"];
403 |
404 | #region Set Image to the new pixels
405 | // encode the bytes to a string, and then the image
406 | // this is for interop with the js extensions
407 | // wouldn't be needed if all extensions were implemented as app services
408 | string encodedImage = await ImageTools.EncodeBytesToPNGString(pixels, (uint)width, (uint)height);
409 | await AppData.currentImage.SetSourceAsync(ImageTools.DecodeStringToBitmapSource(encodedImage));
410 | AppData.currentImageString = encodedImage;
411 | #endregion
412 | }
413 | }
414 | }
415 | }
416 | }
417 | catch (Exception e)
418 | {
419 | MessageDialog md = new MessageDialog("Invoking app service failed!");
420 | await md.ShowAsync();
421 | }
422 | }
423 | #endregion
424 | }
425 | }
426 |
427 | #region Update - NYI
428 | // calls the 'extensionUpdate' function
429 | // this is called whenever the data in the host app is updated so the extension
430 | // can keep track of the changes
431 | public async void InvokeUpdate(string str)
432 | {
433 | if (this._loaded)
434 | {
435 | // the script function may not exist
436 | try
437 | {
438 | await _extwebview.InvokeScriptAsync("extensionUpdate", new string[] { str });
439 | }
440 | catch (Exception e)
441 | {
442 | //MessageDialog md = new MessageDialog("Invoking extension update failed!");
443 | //await md.ShowAsync();
444 | }
445 | }
446 | }
447 | #endregion
448 |
449 |
450 | // called when the javascript in the extension signals a notify
451 | // we use this to receive image data from the callback
452 | private async void ExtensionCallback(object sender, NotifyEventArgs e)
453 | {
454 | if (this._loaded)
455 | {
456 | try
457 | {
458 | string encodedImage = ImageTools.StripDataURIHeader(e.Value);
459 | await AppData.currentImage.SetSourceAsync(ImageTools.DecodeStringToBitmapSource(encodedImage));
460 | AppData.currentImageString = encodedImage;
461 | }
462 | catch (Exception ex)
463 | {
464 | return;
465 | }
466 | }
467 | }
468 |
469 |
470 | public async Task Update(AppExtension ext)
471 | {
472 | // ensure this is the same uid
473 | string identifier = ext.AppInfo.AppUserModelId + "!" + ext.Id;
474 | if (identifier != this.UniqueId)
475 | {
476 | return;
477 | }
478 |
479 | // get extension properties
480 | var properties = await ext.GetExtensionPropertiesAsync() as PropertySet;
481 |
482 | // get logo
483 | var filestream = await (ext.AppInfo.DisplayInfo.GetLogo(new Windows.Foundation.Size(1, 1))).OpenReadAsync();
484 | BitmapImage logo = new BitmapImage();
485 | logo.SetSource(filestream);
486 |
487 | // update the extension
488 | this._extension = ext;
489 | this._properties = properties;
490 | this._logo = logo;
491 |
492 | #region Update Properties
493 | // update app service information
494 | this._serviceName = null;
495 | if (this._properties != null)
496 | {
497 | if (this._properties.ContainsKey("Service"))
498 | {
499 | PropertySet serviceProperty = this._properties["Service"] as PropertySet;
500 | this._serviceName = serviceProperty["#text"].ToString();
501 | }
502 | }
503 | #endregion
504 |
505 | // load it
506 | await Load();
507 | }
508 |
509 | // this controls loading of the extension
510 | public async Task Load()
511 | {
512 | #region Error Checking
513 | // if it's not enabled or already loaded, don't load it
514 | if (!_enabled || _loaded)
515 | {
516 | return;
517 | }
518 |
519 | // make sure package is OK to load
520 | if (!_extension.Package.Status.VerifyIsOK())
521 | {
522 | return;
523 | }
524 | #endregion
525 |
526 | // Extension is not loaded and enabled - load it
527 | StorageFolder folder = await _extension.GetPublicFolderAsync();
528 | if (folder != null)
529 | {
530 | // load the webview html
531 | // this is the html that does not have UI that runs
532 | string fileName = @"extension.html";
533 | StorageFile extensionfile = null;
534 | try
535 | {
536 | extensionfile = await folder.GetFileAsync(fileName);
537 | }
538 | catch (Exception e)
539 | {
540 | // something bad happened
541 | return;
542 | }
543 | if (extensionfile != null)
544 | {
545 | // read entire file as string
546 | string extwebview = await FileIO.ReadTextAsync(extensionfile);
547 |
548 | // load webview and navigate to it
549 | // this is dangerous and for demo purposes only
550 | //you should never load untrusted script
551 | _extwebview.NavigateToString(extwebview);
552 |
553 | // all went well, set state
554 | _loaded = true;
555 | _visibility = Visibility.Visible;
556 | RaisePropertyChanged("Visible");
557 | _offline = false;
558 | }
559 | }
560 | }
561 |
562 | // This enables the extension
563 | public async Task Enable()
564 | {
565 | // indicate desired state is enabled
566 | _enabled = true;
567 |
568 | // load the extension
569 | await Load();
570 | }
571 |
572 | // this is different from Disable, example: during updates where we only want to unload -> reload
573 | // Enable is user intention. Load respects enable, but unload doesn't care
574 | public void Unload()
575 | {
576 | // unload it
577 | lock (_sync)
578 | {
579 | if (_loaded)
580 | {
581 |
582 | // unload the webview
583 | _extwebview.NavigateToString("");
584 |
585 | // see if package is offline
586 | if (!_extension.Package.Status.VerifyIsOK() && !_extension.Package.Status.PackageOffline)
587 | {
588 | _offline = true;
589 | }
590 |
591 | _loaded = false;
592 | _visibility = Visibility.Collapsed;
593 | RaisePropertyChanged("Visible");
594 | }
595 | }
596 | }
597 |
598 | // user-facing action to disable the extension
599 | public void Disable()
600 | {
601 | // only disable if it is enabled
602 | if (_enabled)
603 | {
604 | // set desired state to disabled
605 | _enabled = false;
606 | // unload the app
607 | Unload();
608 | }
609 | }
610 | #region PropertyChanged
611 |
612 | // typical property changed handler
613 | private void RaisePropertyChanged(string name)
614 | {
615 | if (PropertyChanged != null)
616 | {
617 | PropertyChanged(this, new PropertyChangedEventArgs(name));
618 | }
619 | }
620 | #endregion
621 |
622 | }
623 | }
624 |
--------------------------------------------------------------------------------
/ExtensibilitySample/ExtensionsTab.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
15 |
17 |
20 |
26 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/ExtensibilitySample/ExtensionsTab.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Runtime.InteropServices.WindowsRuntime;
7 | using Windows.Foundation;
8 | using Windows.Foundation.Collections;
9 | using Windows.UI.Xaml;
10 | using Windows.UI.Xaml.Controls;
11 | using Windows.UI.Xaml.Controls.Primitives;
12 | using Windows.UI.Xaml.Data;
13 | using Windows.UI.Xaml.Input;
14 | using Windows.UI.Xaml.Media;
15 | using Windows.UI.Xaml.Navigation;
16 |
17 | // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
18 |
19 | namespace ExtensibilitySample
20 | {
21 | ///
22 | /// An empty page that can be used on its own or navigated to within a Frame.
23 | ///
24 | public sealed partial class ExtensionsTab : Page
25 | {
26 |
27 | public ObservableCollection Items = null;
28 | public ObservableCollection Suggestions { get; private set; }
29 |
30 | public ExtensionsTab()
31 | {
32 | this.InitializeComponent();
33 |
34 | this.Suggestions = new ObservableCollection();
35 |
36 | Items = AppData.ExtensionManager.Extensions;
37 | this.DataContext = Items;
38 | }
39 |
40 | private void BackButton_Click(object sender, RoutedEventArgs e)
41 | {
42 | if (this.Frame.CanGoBack)
43 | this.Frame.GoBack();
44 | }
45 |
46 | private async void CheckBox_Checked(object sender, RoutedEventArgs e)
47 | {
48 | CheckBox cb = sender as CheckBox;
49 | Extension ext = cb.DataContext as Extension;
50 | if (!ext.Enabled)
51 | {
52 | await ext.Enable();
53 | }
54 | }
55 |
56 | private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
57 | {
58 | CheckBox cb = sender as CheckBox;
59 | Extension ext = cb.DataContext as Extension;
60 | if (ext.Enabled)
61 | {
62 | ext.Disable();
63 | }
64 | }
65 |
66 | private void RemoveButton_Click(object sender, RoutedEventArgs e)
67 | {
68 | // remove the package
69 | Button btn = sender as Button;
70 | Extension ext = btn.DataContext as Extension;
71 | AppData.ExtensionManager.RemoveExtension(ext);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/ExtensibilitySample/Image.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/ExtensibilitySample/Image.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 | // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
17 |
18 | namespace ExtensibilitySample
19 | {
20 | ///
21 | /// An empty page that can be used on its own or navigated to within a Frame.
22 | ///
23 | public sealed partial class Image : Page
24 | {
25 | public Image()
26 | {
27 | this.InitializeComponent();
28 |
29 | DataContext = AppData.currentImage;
30 |
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ExtensibilitySample/ImageTools.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Runtime.InteropServices.WindowsRuntime;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using Windows.Graphics.Imaging;
8 | using Windows.Storage;
9 | using Windows.Storage.Streams;
10 | using Windows.UI.Xaml.Media.Imaging;
11 |
12 | namespace ExtensibilitySample
13 | {
14 | class ImageTools
15 | {
16 | // adds data uri header to the encoded string for png image
17 | public static string AddDataURIHeader(string encodedString)
18 | {
19 | return "data:image/png;base64," + encodedString;
20 | }
21 |
22 | // converts data URL into the raw string to convert
23 | // this just strips the data URI
24 | public static string StripDataURIHeader(string url)
25 | {
26 | StringBuilder sb = new StringBuilder(url, url.Length);
27 | sb.Replace("data:image/png;base64,", String.Empty);
28 |
29 | // todo: better error checking
30 |
31 | return sb.ToString();
32 | }
33 |
34 | // Converts file to b64 string encoded as a PNG
35 | // regardless of what the input is, it is converted to a PNG in this process :)
36 | public static async Task FileToString(StorageFile source)
37 | {
38 | using (IRandomAccessStream fileStream = await source.OpenAsync(Windows.Storage.FileAccessMode.Read))
39 | {
40 | var destStream = new InMemoryRandomAccessStream();
41 |
42 | // decode the file stream
43 | var decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(fileStream);
44 | BitmapTransform transform = new BitmapTransform();
45 | var pixelData = await decoder.GetPixelDataAsync(
46 | BitmapPixelFormat.Bgra8,
47 | BitmapAlphaMode.Straight,
48 | transform,
49 | ExifOrientationMode.IgnoreExifOrientation,
50 | ColorManagementMode.DoNotColorManage
51 | );
52 |
53 | // encode the bytes
54 | return await EncodeBytesToPNGString(pixelData.DetachPixelData(), decoder.PixelWidth, decoder.PixelHeight);
55 | }
56 | }
57 |
58 | // gets a byte array representing the pixels in a writeable bitmap
59 | public static byte[] GetBitmapBytes(WriteableBitmap bitmap)
60 | {
61 | using (MemoryStream ms = new MemoryStream())
62 | {
63 | // copy pixel buffer to the memory buffer
64 | bitmap.PixelBuffer.AsStream().CopyTo(ms);
65 |
66 | // return buffer as byte array
67 | return ms.ToArray();
68 | }
69 | }
70 |
71 | // encodes bytes into a b64 string in png format, must also specify height and width
72 | public static async Task EncodeBytesToPNGString(byte[] bytes, uint width, uint height)
73 | {
74 | using (IRandomAccessStream destStream = new InMemoryRandomAccessStream())
75 | {
76 | // encoder, assumes input bytes are Bgra8
77 | var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, destStream);
78 | encoder.SetPixelData(
79 | BitmapPixelFormat.Bgra8,
80 | BitmapAlphaMode.Straight,
81 | width,
82 | height,
83 | 96,
84 | 96,
85 | bytes
86 | );
87 |
88 | // encode
89 | await encoder.FlushAsync();
90 |
91 | // convert the stream to bytes
92 | byte[] encodedBytes = new byte[destStream.Size];
93 | destStream.AsStreamForRead().Read(encodedBytes, 0, (int)destStream.Size);
94 |
95 | // and finally encode the bytes to a string
96 | return Convert.ToBase64String(encodedBytes.ToArray());
97 | }
98 | }
99 |
100 | // decode base 64 string into a bitmap
101 | // assumes the string represents an image
102 | public static IRandomAccessStream DecodeStringToBitmapSource(string base64String)
103 | {
104 | var rawBytes = Convert.FromBase64String(base64String);
105 | MemoryStream inputStream = new MemoryStream(rawBytes, 0, rawBytes.Length, false);
106 | return inputStream.AsRandomAccessStream();
107 | }
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/ExtensibilitySample/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
45 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/ExtensibilitySample/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices.WindowsRuntime;
6 | using Windows.Foundation;
7 | using Windows.Foundation.Collections;
8 | using Windows.UI.Xaml;
9 | using Windows.UI.Xaml.Controls;
10 | using Windows.UI.Xaml.Controls.Primitives;
11 | using Windows.UI.Xaml.Data;
12 | using Windows.UI.Xaml.Input;
13 | using Windows.UI.Xaml.Media;
14 | using Windows.UI.Xaml.Navigation;
15 |
16 | // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
17 |
18 | namespace ExtensibilitySample
19 | {
20 | ///
21 | /// An empty page that can be used on its own or navigated to within a Frame.
22 | ///
23 | public sealed partial class MainPage : Page
24 | {
25 | public static MainPage Current;
26 |
27 | public List Tabs
28 | {
29 | get { return this.tabs; }
30 | }
31 | public MainPage()
32 | {
33 | this.InitializeComponent();
34 |
35 | AppData.ExtensionManager.Initialize();
36 |
37 | Current = this;
38 | SampleTitle.Text = "Extensibility Sample";
39 | }
40 |
41 | protected override void OnNavigatedTo(NavigationEventArgs e)
42 | {
43 | // Populate the scenario list from the SampleConfiguration.cs file
44 | ScenarioControl.ItemsSource = tabs;
45 | if (Window.Current.Bounds.Width < 640)
46 | {
47 | ScenarioControl.SelectedIndex = -1;
48 | }
49 | else
50 | {
51 | ScenarioControl.SelectedIndex = 0;
52 | }
53 | }
54 |
55 | private void ScenarioControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
56 | {
57 | // Clear the status block when navigating scenarios.
58 | NotifyUser(String.Empty, NotifyType.StatusMessage);
59 |
60 | ListBox scenarioListBox = sender as ListBox;
61 | Tab s = scenarioListBox.SelectedItem as Tab;
62 | if (s != null)
63 | {
64 | ScenarioFrame.Navigate(s.ClassType);
65 | if (Window.Current.Bounds.Width < 640)
66 | {
67 | Splitter.IsPaneOpen = false;
68 | StatusBorder.Visibility = Visibility.Collapsed;
69 | }
70 | }
71 | }
72 |
73 |
74 | public void NotifyUser(string strMessage, NotifyType type)
75 | {
76 | switch (type)
77 | {
78 | case NotifyType.StatusMessage:
79 | StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Green);
80 | break;
81 | case NotifyType.ErrorMessage:
82 | StatusBorder.Background = new SolidColorBrush(Windows.UI.Colors.Red);
83 | break;
84 | }
85 | StatusBlock.Text = strMessage;
86 |
87 | // Collapse the StatusBlock if it has no text to conserve real estate.
88 | StatusBorder.Visibility = (StatusBlock.Text != String.Empty) ? Visibility.Visible : Visibility.Collapsed;
89 | }
90 |
91 | async void Footer_Click(object sender, RoutedEventArgs e)
92 | {
93 | await Windows.System.Launcher.LaunchUriAsync(new Uri(((HyperlinkButton)sender).Tag.ToString()));
94 | }
95 |
96 | private void Button_Click(object sender, RoutedEventArgs e)
97 | {
98 | Splitter.IsPaneOpen = (Splitter.IsPaneOpen == true) ? false : true;
99 | StatusBorder.Visibility = Visibility.Collapsed;
100 | }
101 |
102 | }
103 |
104 | public enum NotifyType
105 | {
106 | StatusMessage,
107 | ErrorMessage
108 | };
109 |
110 | public class ScenarioBindingConverter : IValueConverter
111 | {
112 | public object Convert(object value, Type targetType, object parameter, string language)
113 | {
114 | Tab s = value as Tab;
115 | return s.Title;
116 | }
117 |
118 | public object ConvertBack(object value, Type targetType, object parameter, string language)
119 | {
120 | return true;
121 | }
122 | }
123 |
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/ExtensibilitySample/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | App Extensibility Demo
7 | Microsoft Corporation
8 | Assets\StoreLogo.png
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | build2016.appextensibility.demo
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/ExtensibilitySample/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ExtensibilitySample")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ExtensibilitySample")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/ExtensibilitySample/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/ExtensibilitySample/Styles/Styles.xaml:
--------------------------------------------------------------------------------
1 |
13 |
17 |
18 |
22 |
23 |
28 |
29 |
34 |
35 |
42 |
43 |
46 |
47 |
52 |
53 |
58 |
59 |
65 |
66 |
71 |
72 |
76 |
77 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/ExtensibilitySample/Tab.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Windows.UI.Xaml.Controls;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace ExtensibilitySample
9 | {
10 |
11 | public partial class MainPage : Page
12 | {
13 | List tabs = new List
14 | {
15 | new Tab() { Title="Image Editor", ClassType=typeof(EditorTab) },
16 | new Tab() { Title="Extensions", ClassType=typeof(ExtensionsTab) }
17 | };
18 | }
19 |
20 | public class Tab
21 | {
22 | public string Title { get; set; }
23 | public Type ClassType { get; set; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ExtensibilitySample/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.ApplicationInsights": "1.0.0",
4 | "Microsoft.ApplicationInsights.PersistenceChannel": "1.0.0",
5 | "Microsoft.ApplicationInsights.WindowsApps": "1.0.0",
6 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
7 | },
8 | "frameworks": {
9 | "uap10.0": {}
10 | },
11 | "runtimes": {
12 | "win10-arm": {},
13 | "win10-arm-aot": {},
14 | "win10-x86": {},
15 | "win10-x86-aot": {},
16 | "win10-x64": {},
17 | "win10-x64-aot": {}
18 | }
19 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Build2016-B808-AppExtensibilitySample
2 | This repo contains the sample shown during the App Extensibility Session during Build 2016
3 |
4 | After cloning the sample, open the solution in Visual Studio. Make sure you're on the Insider version of the Windows Anniversary Update(Build 14295) and you have the associated SDK. This sample is a complete App Extension Host and also shows cropping via LaunchURIForResultsAsync, and includes the Cortana App Service.
5 |
6 | To use actual app extensions, clone the following projects and deploy them from Visual Studio. They should automatically appear in the Extensions tab of the main application.
7 |
8 | Grayscale:
9 | https://github.com/anagamsft/Build2016-GrayscaleExtension
10 |
11 | Invert:
12 | https://github.com/anagamsft/Build2016-InvertExtension
13 |
14 | Rotate:
15 | https://github.com/anagamsft/RotateExtension
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------