├── LICENSE
├── MSIX_Commander.ps1
├── README.md
└── ReleaseNotes.txt
/LICENSE:
--------------------------------------------------------------------------------
1 | Microsoft Public License (Ms-PL)
2 |
3 |
4 |
5 | This license governs use of the accompanying software. If you use the
6 |
7 | software, you accept this license. If you do not accept the license,
8 |
9 | do not use the software.
10 |
11 |
12 |
13 | 1. Definitions
14 |
15 |
16 |
17 | The terms "reproduce," "reproduction," "derivative works," and
18 |
19 | "distribution" have the same meaning here as under U.S. copyright
20 |
21 | law.
22 |
23 |
24 |
25 | A "contribution" is the original software, or any additions or
26 |
27 | changes to the software.
28 |
29 |
30 |
31 | A "contributor" is any person that distributes its contribution
32 |
33 | under this license.
34 |
35 |
36 |
37 | "Licensed patents" are a contributor's patent claims that read
38 |
39 | directly on its contribution.
40 |
41 |
42 |
43 | 2. Grant of Rights
44 |
45 |
46 |
47 | (A) Copyright Grant- Subject to the terms of this license,
48 |
49 | including the license conditions and limitations in section 3,
50 |
51 | each contributor grants you a non-exclusive, worldwide,
52 |
53 | royalty-free copyright license to reproduce its contribution,
54 |
55 | prepare derivative works of its contribution, and distribute its
56 |
57 | contribution or any derivative works that you create.
58 |
59 |
60 |
61 | (B) Patent Grant- Subject to the terms of this license, including
62 |
63 | the license conditions and limitations in section 3, each
64 |
65 | contributor grants you a non-exclusive, worldwide, royalty-free
66 |
67 | license under its licensed patents to make, have made, use, sell,
68 |
69 | offer for sale, import, and/or otherwise dispose of its
70 |
71 | contribution in the software or derivative works of the
72 |
73 | contribution in the software.
74 |
75 |
76 |
77 | 3. Conditions and Limitations
78 |
79 |
80 |
81 | (A) No Trademark License- This license does not grant you rights
82 |
83 | to use any contributors' name, logo, or trademarks.
84 |
85 |
86 |
87 | (B) If you bring a patent claim against any contributor over
88 |
89 | patents that you claim are infringed by the software, your patent
90 |
91 | license from such contributor to the software ends automatically.
92 |
93 |
94 |
95 | (C) If you distribute any portion of the software, you must retain
96 |
97 | all copyright, patent, trademark, and attribution notices that are
98 |
99 | present in the software.
100 |
101 |
102 |
103 | (D) If you distribute any portion of the software in source code
104 |
105 | form, you may do so only under this license by including a
106 |
107 | complete copy of this license with your distribution. If you
108 |
109 | distribute any portion of the software in compiled or object code
110 |
111 | form, you may only do so under a license that complies with this
112 |
113 | license.
114 |
115 |
116 |
117 | (E) The software is licensed "as-is." You bear the risk of using
118 |
119 | it. The contributors give no express warranties, guarantees, or
120 |
121 | conditions. You may have additional consumer rights under your
122 |
123 | local laws which this license cannot change. To the extent
124 |
125 | permitted under your local laws, the contributors exclude the
126 |
127 | implied warranties of merchantability, fitness for a particular
128 |
129 | purpose and non-infringement.
130 |
--------------------------------------------------------------------------------
/MSIX_Commander.ps1:
--------------------------------------------------------------------------------
1 | $ScriptVersion = "1.0.7.5"
2 | # Add required assemblies for icon
3 | Add-Type -AssemblyName PresentationFramework, System.Drawing, System.Windows.Forms, WindowsFormsIntegration
4 |
5 | #region GUI
6 | #ERASE ALL THIS AND PUT XAML BELOW between the @" "@
7 | $inputXML = @"
8 |
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 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 | "@
227 |
228 | $inputXML = $inputXML -replace 'mc:Ignorable="d"','' -replace "x:N",'N' -replace '^
254 |
255 | }
256 |
257 | Get-FormVariables
258 |
259 | #endregion
260 |
261 |
262 | #region Functions
263 |
264 | Function Open-Eventlogs{
265 |
266 | try{
267 |
268 | $EventLogsCount = 0
269 | $AllEvents = @()
270 | [Double]$TimePeriod = $WPFTextBox_OpenEventLogsHours.Text
271 | $LastHours = $TimePeriod * 3600000
272 |
273 | $AppxLogs =((Get-WinEvent -ListLog *Microsoft-Windows-*Appx* -ErrorAction SilentlyContinue).Logname).split(" ")
274 |
275 | $AppxLogsCount = $AppxLogs.count
276 | ForEach($AppxLog in $AppxLogs){
277 |
278 | $filterXml = @"
279 |
280 |
281 |
282 |
283 |
284 | "@
285 | $Events = Get-WinEvent -filterXml $filterXml -ErrorAction SilentlyContinue
286 | IF($Events) {
287 | $Events | Out-GridView -Title "EventLog: $AppxLog" -ErrorAction SilentlyContinue
288 | $EventLogsCount = $EventLogsCount+1
289 | $AllEvents += $Events
290 |
291 | }
292 | }
293 |
294 | $AllEvents |Sort-Object TimeCreated -Descending | Out-GridView -Title "Consolidated Events from all $EventLogsCount Log(s)"
295 |
296 | $WPFTextBox_Messages.Text = "From $AppxLogsCount MSIX Eventlogs, $EventLogsCount had Events that hapennd in the last $TimePeriod hour(s). I opend only those."
297 | $WPFTextBox_Messages.Foreground = "Black"
298 |
299 |
300 | }
301 | catch{
302 | $ErrorMessage = $_.Exception.Message
303 | $WPFTextBox_Messages.Text = ("Couldn't opend Event Logs / $ErrorMessage")
304 | $WPFTextBox_Messages.Foreground = "Red"
305 | }
306 | }
307 |
308 | Function ConvertTo-VHD {
309 |
310 | param(
311 | [Parameter(Mandatory=$true)]
312 | [String]
313 | $Path
314 | )
315 | #region variables
316 | $msixmgrURL = "https://aka.ms/msixmgr"
317 | $TempFolder= "$env:TEMP\_CreatAppAttachMSIX"
318 | $MsixmgrZip = "$env:TEMP\_msixmgr.zip"
319 | $MsixmgrFolder = "$TempFolder\_msixmgr"
320 | $Extractfolder = "$env:SystemDrive\TempExtractAppAttach"
321 | If([Environment]::Is64BitOperatingSystem){
322 | $MsixmgrExe = "$MsixmgrFolder\x64\msixmgr.exe"
323 | }
324 | else{
325 | $MsixmgrExe = "$MsixmgrFolder\x86\msixmgr.exe"
326 |
327 | }
328 |
329 | #endregion
330 |
331 | $Scriptblock1Stage = {
332 | #MSIX app attach staging sample
333 |
334 |
335 | #region variables
336 |
337 | $ScriptParentPath = $MyInvocation.MyCommand.Path -replace $myInvocation.MyCommand.Name,""
338 |
339 | $vhdSrc = (get-ChildItem -Path $ScriptParentPath -Filter *.vhd)[0].FullName
340 |
341 | Write-Host "VHD $vhdSrc found"
342 |
343 |
344 | $JSONFileName = "AppAttachInfo.json"
345 |
346 | $msixJunction = "$Env:Temp\AppAttach\"
347 |
348 | #endregion
349 |
350 | #region mountvhd
351 |
352 | try{
353 | $VHDFolder = (Get-Item $vhdSrc).DirectoryName
354 | $JsonFile = "$VHDFolder\$JSONFileName"
355 |
356 | If(Test-Path -Path $JsonFile){
357 | $Json = get-content $JsonFile |ConvertFrom-Json
358 |
359 | $MountedVHD = Mount-DiskImage -ImagePath $vhdSrc -NoDriveLetter -Access ReadOnly
360 |
361 | $msixDest = $Json.PartitionPath
362 | $packageName = $Json.PackageName
363 |
364 | $parentFolder = $Json.ParentFolder
365 | $parentFolder = "\" + $parentFolder + "\"
366 | }
367 | else{
368 | Write-Host "$JsonFile not found"
369 | }
370 | }
371 | catch
372 | {
373 | Write-Host ("Mounting of " + $vhdSrc + " has failed!") -BackgroundColor Red
374 | }
375 |
376 | #endregion
377 |
378 | #region makelink
379 |
380 | if (!(Test-Path $msixJunction)){
381 | md $msixJunction
382 | }
383 |
384 | $msixJunction = $msixJunction + $packageName
385 |
386 | cmd.exe /c mklink /j $msixJunction $msixDest
387 |
388 | #endregion
389 |
390 | #region stage
391 |
392 | [Windows.Management.Deployment.PackageManager,Windows.Management.Deployment,ContentType=WindowsRuntime]| Out-Null
393 |
394 | Add-Type -AssemblyName System.Runtime.WindowsRuntime
395 |
396 | $asTask = ([System.WindowsRuntimeSystemExtensions].GetMethods() | Where {
397 | $_.ToString() -eq 'System.Threading.Tasks.Task`1[TResult] AsTask[TResult,TProgress](Windows.Foundation.IAsyncOperationWithProgress`2[TResult,TProgress])'
398 | })[0]
399 |
400 | $asTaskAsyncOperation =
401 | $asTask.MakeGenericMethod([Windows.Management.Deployment.DeploymentResult],
402 | [Windows.Management.Deployment.DeploymentProgress])
403 |
404 | $packageManager = [Windows.Management.Deployment.PackageManager]::new()
405 |
406 | $path = $msixJunction + $parentFolder + $packageName # needed if we do the pbisigned.vhd
407 |
408 | $path = ([System.Uri]$path).AbsoluteUri
409 |
410 | $asyncOperation = $packageManager.StagePackageAsync("$path", $null, "StageInPlace")
411 |
412 | $task = $asTaskAsyncOperation.Invoke($null, @($asyncOperation))
413 |
414 | Do{
415 | Start-Sleep -Milliseconds 100
416 | }Until(($task.IsCompleted -eq $true) -or ($task.IsFaulted -eq $true))
417 |
418 | $task.Exception
419 | $task.Status
420 |
421 | #endregion
422 |
423 |
424 |
425 |
426 | }
427 |
428 | $Scriptblock2Register = {
429 | #MSIX app attach registration sample
430 |
431 |
432 | #region variables
433 |
434 | $ScriptParentPath = $MyInvocation.MyCommand.Path -replace $myInvocation.MyCommand.Name,""
435 |
436 | $vhdSrc = (get-ChildItem -Path $ScriptParentPath -Filter *.vhd)[0].FullName
437 |
438 | Write-Host "VHD $vhdSrc found"
439 |
440 |
441 | $JSONFileName = "AppAttachInfo.json"
442 | $VHDFolder = (Get-Item $vhdSrc).DirectoryName
443 | $JsonFile = "$VHDFolder\$JSONFileName"
444 |
445 |
446 | If(Test-Path -Path $JsonFile){
447 | $Json = get-content $JsonFile |ConvertFrom-Json
448 | $packageName = $Json.PackageName
449 | }
450 | else{
451 | Write-Host "$JsonFile not found"
452 | }
453 |
454 | #endregion
455 |
456 | #region register
457 |
458 | $path = "C:\Program Files\WindowsApps\" + $packageName + "\AppxManifest.xml"
459 | Add-AppxPackage -Path $path -DisableDevelopmentMode -Register
460 |
461 |
462 | #endregion
463 |
464 |
465 | }
466 |
467 | $Scriptblock3Deregister = {
468 | #MSIX app attach deregistration sample
469 |
470 |
471 |
472 | #region variables
473 | $ScriptParentPath = $MyInvocation.MyCommand.Path -replace $myInvocation.MyCommand.Name,""
474 |
475 | $vhdSrc = (get-ChildItem -Path $ScriptParentPath -Filter *.vhd)[0].FullName
476 |
477 | Write-Host "VHD $vhdSrc found"
478 |
479 |
480 | $JSONFileName = "AppAttachInfo.json"
481 | $VHDFolder = (Get-Item $vhdSrc).DirectoryName
482 | $JsonFile = "$VHDFolder\$JSONFileName"
483 |
484 | If(Test-Path -Path $JsonFile){
485 | $Json = get-content $JsonFile |ConvertFrom-Json
486 | $packageName = $Json.PackageName
487 | }
488 | else{
489 | Write-Host "$JsonFile not found"
490 | }
491 |
492 |
493 | #endregion
494 |
495 | #region deregister
496 |
497 | Remove-AppxPackage -PreserveRoamableApplicationData $packageName
498 |
499 | #endregion
500 |
501 | }
502 |
503 | $Scriptblock4Destage = {
504 | #MSIX app attach de staging sample
505 |
506 |
507 | #region variables
508 |
509 | $ScriptParentPath = $MyInvocation.MyCommand.Path -replace $myInvocation.MyCommand.Name,""
510 |
511 | $vhdSrc = (get-ChildItem -Path $ScriptParentPath -Filter *.vhd)[0].FullName
512 |
513 | Write-Host "VHD $vhdSrc found"
514 |
515 |
516 | $JSONFileName = "AppAttachInfo.json"
517 | $VHDFolder = (Get-Item $vhdSrc).DirectoryName
518 | $JsonFile = "$VHDFolder\$JSONFileName"
519 |
520 | $msixJunction = "$Env:Temp\AppAttach\"
521 |
522 | #endregion
523 |
524 |
525 |
526 | If(Test-Path -Path $JsonFile){
527 | $Json = get-content $JsonFile |ConvertFrom-Json
528 | $packageName = $Json.PackageName
529 | $PackageMountPoint = "$msixJunction\$packageName"
530 | }
531 | else{
532 | Write-Host "$JsonFile not found"
533 | }
534 |
535 |
536 | #region deregister
537 |
538 | Remove-AppxPackage -AllUsers -Package $packageName
539 |
540 | #cd $msixJunction
541 |
542 | Remove-Item -Path $PackageMountPoint -Recurse -Force
543 |
544 | # rmdir $packageName -Force -Verbose
545 |
546 |
547 | Dismount-DiskImage -ImagePath $vhdSrc
548 |
549 | #endregion
550 |
551 | }
552 |
553 | #Check if user is Admin
554 | If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")) {
555 | #If he is an Admin
556 |
557 | $VBS = new-object -comobject wscript.shell
558 |
559 | $CleandUpPath = $Path.replace('"',"")
560 |
561 |
562 | If(!-(Test-Path $TempFolder)){
563 | New-Item $TempFolder -ItemType directory
564 | }
565 |
566 | IF(Test-Path -Path $CleandUpPath){
567 |
568 |
569 | If((get-item -Path $CleandUpPath).Extension.ToUpper() -eq ".MSIX"){
570 | $FoundPackages = get-item -Path $CleandUpPath
571 | }
572 | else{
573 | $FoundPackages = (Get-ChildItem -Path $CleandUpPath -Recurse -Filter "*.msix" ) | Sort-Object
574 | }
575 |
576 |
577 | If($FoundPackages.count -ne 1){
578 | $WPFTextBox_Messages.Text = ("In the new window, select all the MSIX packages you want to convert")
579 | $WPFTextBox_Messages.Foreground = "Black"
580 |
581 | $SelctedPackages = $FoundPackages | Select-Object -Property Name,FullName |Out-GridView -Title ("Select MSIX files you want to convert ("+$FoundPackages.count+")" ) -OutputMode Multiple | Select-Object -Property Fullname,Name
582 | }
583 | else{
584 | $SelctedPackages = $FoundPackages
585 | }
586 |
587 |
588 | If($SelctedPackages.FullName.count -ge 1){
589 |
590 | If(-!(Test-Path $MsixmgrExe)){
591 | Invoke-WebRequest -Uri $msixmgrURL -OutFile $MsixmgrZip -PassThru -UseBasicParsing
592 |
593 | If((Test-Path $MsixmgrZip)){
594 | Expand-Archive -Path $MsixmgrZip -DestinationPath $MsixmgrFolder
595 | If(-!(Test-Path $MsixmgrExe)){
596 | $ErrorMessage = $_.Exception.Message
597 | $WPFTextBox_Messages.Text = ("I couldn't extract the Msixmgr Tool from $MsixmgrZip" +" / $ErrorMessage")
598 | $WPFTextBox_Messages.Foreground = "Red"
599 | Return
600 | }
601 | }
602 | else{
603 | $ErrorMessage = $_.Exception.Message
604 | $WPFTextBox_Messages.Text = ("I couldn't download the Msixmgr Tool from $msixmgrURL" +" / $ErrorMessage")
605 | $WPFTextBox_Messages.Foreground = "Red"
606 | Return
607 | }
608 | }
609 |
610 |
611 | ForEach($MSIX in $SelctedPackages){
612 | $Message = ""
613 |
614 | try{
615 |
616 | $MSIXCopy = "$TempFolder\" +$MSIX.Name
617 | Copy-Item $MSIX.fullname -Destination $MSIXCopy -Force
618 |
619 | $MSIXObject = Get-Item $MSIXCopy
620 | $MSIXName = $MSIXObject.Name.Replace($MSIXObject.Extension,"").Replace(" ","")
621 |
622 | $OutPutFolder = "$TempFolder\$MSIXName"
623 |
624 | If(Test-path $OutPutFolder){
625 | Remove-Item $OutPutFolder -Force -Recurse
626 | }
627 | new-item -Path $OutPutFolder -ItemType Directory
628 |
629 | $ParentFolder = "PartenFolder_" +$MSIXName
630 | $VHDFile = "$OutPutFolder\$MSIXName.vhd"
631 |
632 | $ZipFile = Copy-Item $MSIXCopy -Destination ("$TempFolder\" +$MSIXObject.Name.Replace($MSIXObject.Extension,".ZIP")) -Force -PassThru
633 |
634 | If(Test-path $Extractfolder){
635 | Remove-Item $Extractfolder -Force -Recurse
636 | }
637 |
638 | Expand-Archive -Path $ZipFile -DestinationPath $Extractfolder -Force
639 |
640 |
641 | $NeededSize = (((Get-ChildItem $Extractfolder -Recurse | measure Length -s).sum) * 2)
642 |
643 |
644 | If($NeededSize -lt 6815744){
645 | $NeededSize = 6.5MB
646 | }
647 | else{
648 | $NeededSize = ([System.Math]::ceiling($NeededSize/1MB))*1024*1024
649 | }
650 |
651 | $DiskpartFailed = $false
652 | $NeededSize = ([math]::round($NeededSize /1mb)) +21
653 |
654 | $ArgumentCreateVdisk = "create vdisk file=""$VHDFile"" maximum=$NeededSize type=expandable"
655 | $ArgumentCreateVolume = "select vdisk file=""$VHDFile""
656 | attach vdisk
657 | create partition primary
658 | format fs=ntfs
659 | assign
660 | detail"
661 |
662 | $DiskPartSrciptFileCreateVHD ="$TempFolder\DiskpartCreateVHD.txt"
663 | $DiskPartSrciptFileCreateVolume ="$TempFolder\DiskpartCreateVolume.txt"
664 |
665 | $ArgumentCreateVdisk | Out-File -FilePath $DiskPartSrciptFileCreateVHD -Force -NoNewline -NoClobber -Encoding utf8
666 | $ArgumentCreateVolume | Out-File -FilePath $DiskPartSrciptFileCreateVolume -Force -NoNewline -NoClobber -Encoding utf8
667 |
668 | $process = Start-Process -FilePath diskpart.exe -ArgumentList "/S $DiskPartSrciptFileCreateVHD" -WindowStyle Hidden -Wait -PassThru
669 |
670 | If($process.ExitCode -ne 0){
671 | $WPFTextBox_Messages.Text = ("I couldn't create vhd $VHDFile")
672 | $WPFTextBox_Messages.Foreground = "Red"
673 | return
674 | }
675 |
676 |
677 | $VolumesBefore = Get-Volume | Where-Object DriveLetter -ne $null
678 |
679 | $CreatVolumeReturn=(DISKPART /S $DiskPartSrciptFileCreateVolume)
680 | $VolumesAfter= Get-Volume | Where-Object DriveLetter -ne $null
681 |
682 | #Find the new Volume
683 | $NewVolume = @()
684 | ForEach($VolumeAfter in $VolumesAfter){
685 | $TrueCount = 0
686 | ForEach($VolumeBefore in $VolumesBefore){
687 | If($VolumeBefore.DriveLetter -eq $VolumeAfter.DriveLetter){
688 | $TrueCount = $TrueCount +1
689 | }
690 | }
691 | If($TrueCount -eq 0){
692 | $NewVolume += $VolumeAfter
693 | }
694 | }
695 |
696 |
697 | If($NewVolume.count -lt 1){
698 | $WPFTextBox_Messages.Text = ("Found no new driveletter mounting the vhd failed")
699 | $WPFTextBox_Messages.Foreground = "Red"
700 | return
701 | }
702 | elseIf($NewVolume.count -gt 1){
703 | $WPFTextBox_Messages.Text = ("Found to many new driveletters please try again")
704 | $WPFTextBox_Messages.Foreground = "Red"
705 | return
706 | }
707 |
708 | $PartenFolderPath = ($NewVolume.DriveLetter +":\$ParentFolder").tostring()
709 |
710 |
711 |
712 | $Destiantion = $PartenFolderPath
713 |
714 | $MisxmgrArgument = "-Unpack -packagePath ""$MSIXCopy"" -destination ""$Destiantion"" -applyacls"
715 |
716 | $Result = Start-Process -FilePath $MsixmgrExe -ArgumentList ($MisxmgrArgument) -Wait -PassThru -WindowStyle Hidden
717 |
718 |
719 | IF($Result.ExitCode -ne 0){
720 | $WPFTextBox_Messages.Text = ("Failed to extract MSIX using: $MsixmgrExe $MisxmgrArgument" )
721 | $WPFTextBox_Messages.Foreground = "Red"
722 | return
723 | }
724 |
725 | $PackageName = (Get-ChildItem -Path $Destiantion -Directory).Name
726 |
727 | If($PackageName){
728 |
729 | $AppAttachInfo = New-Object -TypeName psobject
730 |
731 | $AppAttachInfo | Add-Member -MemberType NoteProperty -Name MSIXName -Value $MSIXObject.Name
732 | $AppAttachInfo | Add-Member -MemberType NoteProperty -Name PartitionPath -Value $NewVolume.Path
733 | $AppAttachInfo | Add-Member -MemberType NoteProperty -Name ParentFolder -Value $ParentFolder
734 | $AppAttachInfo | Add-Member -MemberType NoteProperty -Name PackageName -Value $PackageName
735 | }
736 | else{
737 | throw
738 | }
739 |
740 | $AppAttachInfo | ConvertTo-Json | Out-File -FilePath ("$OutPutFolder\AppAttachInfo.json")
741 |
742 |
743 | $CertContent= (Get-AuthenticodeSignature -FilePath $MSIXCopy ).SignerCertificate
744 | $CertToExport = "$OutPutFolder\$MSIXName.cer"
745 | If($CertContent){
746 | Export-Certificate -Cert $CertContent -FilePath $CertToExport -Force
747 | }
748 |
749 | #Generate Mountig Scripts
750 | $Scriptblock1Stage.ToString() | out-file -FilePath "$OutPutFolder\1_Stage.ps1" -Force
751 | $Scriptblock2Register.ToString() | out-file -FilePath "$OutPutFolder\2_Register.ps1" -Force
752 | $Scriptblock3Deregister.ToString() | out-file -FilePath "$OutPutFolder\3_Deregister.ps1" -Force
753 | $Scriptblock4Destage.ToString() | out-file -FilePath "$OutPutFolder\4_Destage.ps1" -Force
754 |
755 | }catch{
756 | $ErrorMessage = $_.Exception.Message
757 |
758 | $WPFTextBox_Messages.Text = ("Failed to convert MSIX " +$MSIXName +" / $ErrorMessage")
759 | $WPFTextBox_Messages.Foreground = "Red"
760 |
761 | $VBS.popup(("Failed to convert MSIX " +$MSIXName +"`n`n$ErrorMessage"),0,"Error",16)
762 | }
763 | Finally{
764 | #CleanUp
765 | If(Test-Path $DiskPartSrciptFileCreateVHD){
766 | remove-item -Path $DiskPartSrciptFileCreateVHD -Force
767 | }
768 |
769 | If(Test-Path $DiskPartSrciptFileCreateVolume){
770 | remove-item -Path $DiskPartSrciptFileCreateVolume -Force
771 | }
772 |
773 | Remove-Item $ZipFile -Force -ErrorAction SilentlyContinue
774 | Remove-Item $Extractfolder -Force -Recurse -ErrorAction SilentlyContinue
775 | Remove-Item -Path $MSIXCopy -Force -ErrorAction SilentlyContinue
776 |
777 | #Detach VHD
778 | $ArgumentDetachVDisk = "select vdisk file=""$VHDFile""
779 | DETACH vdisk"
780 |
781 | $DiskPartSrciptFileDetachVDisk ="$TempFolder\DiskpartDetachVDisk.txt"
782 |
783 | $ArgumentDetachVDisk | Out-File -FilePath $DiskPartSrciptFileDetachVDisk -Force -NoNewline -NoClobber -Encoding utf8
784 |
785 | $process = Start-Process -FilePath diskpart.exe -ArgumentList "/S $DiskPartSrciptFileDetachVDisk" -WindowStyle Hidden -Wait -PassThru
786 |
787 | If(Test-Path $DiskPartSrciptFileDetachVDisk){
788 | remove-item -Path $DiskPartSrciptFileDetachVDisk -Force
789 | }
790 | If($process.ExitCode -ne 0){
791 | $WPFTextBox_Messages.Text = ("Failed to detach $VHDFile")
792 | $WPFTextBox_Messages.Foreground = "Red"
793 | }
794 |
795 | }
796 |
797 | }
798 |
799 | $WPFTextBox_Messages.Text = ("All selected " +$SelctedPackages.count +" Packages are converted.")
800 | $WPFTextBox_Messages.Foreground = "Black"
801 | explorer.exe $TempFolder
802 | }
803 | else{
804 | $WPFTextBox_Messages.Text = ("No MSIX packages selected")
805 | $WPFTextBox_Messages.Foreground = "Red"
806 | }
807 | }
808 | else{
809 | $WPFTextBox_Messages.Text = ("File or Folder not found $CleandUpPath")
810 | $WPFTextBox_Messages.Foreground = "Red"
811 | }
812 | }
813 | else{
814 | #If he is NO Admin
815 | $WPFTextBox_Messages.Text = "You are not an administrator. This Action requieres the tool to be run as an administrator!"
816 | $WPFTextBox_Messages.Foreground = "Red"
817 | Return
818 | }
819 |
820 | }
821 |
822 | Function Open-Tool{
823 |
824 | param(
825 | [Parameter(Mandatory=$true)]
826 | [String]
827 | $tool
828 | )
829 | $SelectedMSIX = $null
830 | $SelectedMSIX = $WPFListView_MSIXPackages.SelectedItem.Name
831 | $SelectedMSIXInstallLocation= $WPFListView_MSIXPackages.SelectedItem.InstallLocation
832 |
833 | $SelectedMSIXInstallPublisherHash = $SelectedMSIXInstallLocation.Substring($SelectedMSIXInstallLocation.LastIndexOf("_")+1,$SelectedMSIXInstallLocation.Length -$SelectedMSIXInstallLocation.LastIndexOf("_")-1)
834 | $UserDataLocation = "$env:LOCALAPPDATA\Packages\$SelectedMSIX"+"_"+$SelectedMSIXInstallPublisherHash
835 |
836 |
837 | If($MSIXData){
838 | IF($SelectedMSIX){
839 | try{
840 | $Package = Get-AppxPackage -Name $SelectedMSIX
841 | $Manifest = Get-AppxPackageManifest -package $Package
842 | $AppId = $Manifest.package.Applications.Application.Id
843 | Invoke-CommandInDesktopPackage -PackageFamilyName $Package.PackageFamilyName -PreventBreakaway -command $tool -AppId $AppId
844 | $WPFTextBox_Messages.Text = "Opend $tool inside MSIX $SelectedMSIX"
845 | $WPFTextBox_Messages.Foreground = "Black"
846 | }
847 | catch{
848 | $ErrorMessage = $_.Exception.Message
849 | $WPFTextBox_Messages.Text = ("Couldn't opend $tool inside MSIX $SelectedMSIX / $ErrorMessage")
850 | $WPFTextBox_Messages.Foreground = "Red"
851 | }
852 | }
853 | else{
854 | $WPFTextBox_Messages.Text = "You need to select a MSIX first"
855 | $WPFTextBox_Messages.Foreground = "Black"
856 | }
857 | }
858 | else{
859 | $WPFTextBox_Messages.Text = "You need to get the Software first and then select an MSIX!"
860 | $WPFTextBox_Messages.Foreground = "Black"
861 | }
862 | }
863 |
864 | Function Enable-DeveloperMode{
865 |
866 | try{
867 | $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
868 | $Name1 = "AllowAllTrustedApps"
869 | $Name2 = "AllowDevelopmentWithoutDevLicense"
870 | $value1 = "1"
871 | $value2 = "1"
872 |
873 | New-ItemProperty -Path $registryPath -Name $name1 -Value $value1 -PropertyType DWORD -Force -ErrorAction Stop
874 | New-ItemProperty -Path $registryPath -Name $name2 -Value $value2 -PropertyType DWORD -Force -ErrorAction Stop
875 |
876 | $WPFTextBox_Messages.Text = ("Developer Mode succesfully enablead")
877 | $WPFTextBox_Messages.Foreground = "Green"
878 |
879 | }
880 | catch{
881 | $ErrorMessage = $_.Exception.Message
882 | $WPFTextBox_Messages.Text = ("Couldn't enable Developer Mode / $ErrorMessage")
883 | $WPFTextBox_Messages.Foreground = "Red"
884 | }
885 | }
886 |
887 | Function Enable-Sideloading{
888 |
889 | try{
890 | $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
891 | $Name1 = "AllowAllTrustedApps"
892 | $Name2 = "AllowDevelopmentWithoutDevLicense"
893 | $value1 = "1"
894 | $value2 = "0"
895 |
896 | New-ItemProperty -Path $registryPath -Name $name1 -Value $value1 -PropertyType DWORD -Force -ErrorAction Stop
897 | New-ItemProperty -Path $registryPath -Name $name2 -Value $value2 -PropertyType DWORD -Force -ErrorAction Stop
898 |
899 | $WPFTextBox_Messages.Text = ("Sideloading succesfully enablead")
900 | $WPFTextBox_Messages.Foreground = "Green"
901 |
902 | }
903 | catch{
904 | $ErrorMessage = $_.Exception.Message
905 | $WPFTextBox_Messages.Text = ("Couldn't enable Sideloading / $ErrorMessage")
906 | $WPFTextBox_Messages.Foreground = "Red"
907 | }
908 | }
909 |
910 | Function Disable-Sideloading{
911 |
912 | try{
913 | $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
914 | $Name1 = "AllowAllTrustedApps"
915 | $Name2 = "AllowDevelopmentWithoutDevLicense"
916 | $value1 = "0"
917 |
918 | New-ItemProperty -Path $registryPath -Name $name1 -Value $value1 -PropertyType DWORD -Force -ErrorAction Stop
919 | New-ItemProperty -Path $registryPath -Name $name2 -Value $value1 -PropertyType DWORD -Force -ErrorAction Stop
920 |
921 | $WPFTextBox_Messages.Text = ("Sideloading succesfully disabled")
922 | $WPFTextBox_Messages.Foreground = "Green"
923 |
924 | }
925 | catch{
926 | $ErrorMessage = $_.Exception.Message
927 | $WPFTextBox_Messages.Text = ("Couldn't disable Sideloading / $ErrorMessage")
928 | $WPFTextBox_Messages.Foreground = "Red"
929 | }
930 | }
931 |
932 | function Check-SideloadingStaus{
933 |
934 | $registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
935 | $Name1 = "AllowAllTrustedApps"
936 | $Name2 = "AllowDevelopmentWithoutDevLicense"
937 |
938 | If((Get-ItemProperty -Path $registryPath -ErrorAction SilentlyContinue).$Name1 -eq 1){
939 | If((Get-ItemProperty -Path $registryPath -ErrorAction SilentlyContinue).$Name2 -eq 1){
940 | "Developer Mode Enabled"
941 | }
942 | else{
943 | "Enabled"
944 | }
945 | }
946 | else{
947 | "Disabled"
948 | }
949 |
950 | }
951 |
952 | Function Change-Signature {
953 |
954 | param(
955 | [Parameter(Mandatory=$true)]
956 | [String]
957 | $Path
958 | )
959 |
960 | $VBS = new-object -comobject wscript.shell
961 |
962 |
963 | $CleandUpPath = $Path.replace('"',"")
964 |
965 | $pfxPath = ($WPFTextBox_ChangeSignature_SelectedCert.Text).replace('"',"")
966 | $Password = $WPFPasswordBox_ChangeSignatureCertPassword.Password
967 |
968 | $TimeStampServer = $WPFTextBox_ChangeSignature_Timeserver.Text
969 |
970 |
971 | If(($pfxPath) -and ($Password)){
972 | #Get the SDK Tools
973 | $MSIXPackagingToolInstallLocation = (Get-AppxPackage -Name "Microsoft.MsixPackagingTool*").InstallLocation
974 | If($MSIXPackagingToolInstallLocation){
975 |
976 | $MsixPackagingToolSDK = "$env:TEMP\MsixPackagingToolSDK"
977 | Copy-Item -Path "$MSIXPackagingToolInstallLocation\SDK" -Destination $MsixPackagingToolSDK -Recurse -Force
978 |
979 | $makeappxPath = "$MsixPackagingToolSDK\makeappx.exe"
980 | $SignTool = "$MsixPackagingToolSDK\signtool.exe"
981 |
982 | $NewMSIXFolder = "$env:TEMP\_NewMSIXFiles\"
983 |
984 | IF(Test-Path -Path $CleandUpPath){
985 | If((get-item -Path $CleandUpPath).Extension.ToUpper() -eq ".MSIX"){
986 | $SelctedPackages = get-item -Path $CleandUpPath
987 | }
988 | else{
989 | $SelctedPackages = (Get-ChildItem -Path $CleandUpPath -Recurse -Filter "*.msix" ) | Sort-Object
990 | }
991 |
992 | ForEach($package in $SelctedPackages){
993 |
994 | try{
995 |
996 | $SelectedMSIX = get-item -path $package.fullname
997 |
998 | $ExtractFolderName = $SelectedMSIX.Name.Replace($SelectedMSIX.Extension,"")
999 |
1000 | $ExtractPath = "$env:TEMP\$ExtractFolderName"
1001 |
1002 | If(Test-Path -Path $ExtractPath){
1003 | Remove-Item -Force -Path $ExtractPath -Recurse
1004 | }
1005 |
1006 | $UnpackParmas ="unpack -v -d ""$ExtractPath"" -p ""$SelectedMSIX"" -o"
1007 |
1008 |
1009 | #Extract MSIX
1010 | $process = Start-Process -FilePath $makeappxPath -ArgumentList $UnpackParmas -Wait -WindowStyle Hidden -PassThru
1011 |
1012 | If($process.exitcode -ne 0){
1013 | write-host $makeappxPath
1014 | write-host $UnpackParmas
1015 | throw
1016 | }
1017 |
1018 | $ManifestXMLPath = "$ExtractPath\AppxManifest.xml"
1019 |
1020 | $ManifestContent = [XML](Get-Content -Path $ManifestXMLPath)
1021 |
1022 | #Get infos from cert
1023 | $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
1024 | $cert.Import($pfxPath,$Password,'DefaultKeySet')
1025 |
1026 | $NewPublisher = $cert.Subject
1027 | $OldPublisher = $ManifestContent.Package.Identity.Publisher
1028 |
1029 | If($OldPublisher -ne $NewPublisher){
1030 | $ManifestContent.Package.Identity.Publisher = $NewPublisher
1031 | }
1032 |
1033 | #Check if Modification Package
1034 | $ModificationPackagePublisher = $ManifestContent.Package.Dependencies.MainPackageDependency.Publisher
1035 | If($OldPublisher -eq $ModificationPackagePublisher){
1036 | $Answer =$VBS.Popup(($package.Name +" is a modifiaction Package.`nThe Publisher of this Package and of the MainPackageDependency are identical.`n`nDo you want me to also update the MainPackageDependency publisher?"),0,"Modification Package",36)
1037 | If($Answer -eq 6){
1038 | $ManifestContent.Package.Dependencies.MainPackageDependency.Publisher = $NewPublisher
1039 | }
1040 | }
1041 |
1042 | #Save NewXML
1043 | $ManifestContent.Save($ManifestXMLPath)
1044 |
1045 | If((Test-Path $NewMSIXFolder) -eq $false){
1046 | md $NewMSIXFolder
1047 | }
1048 |
1049 | $NewMSIXPath = "$NewMSIXFolder\$ExtractFolderName.msix"
1050 |
1051 | $MakeAppxParmas ="pack -d ""$ExtractPath"" -p ""$NewMSIXPath"" -o"
1052 |
1053 | $process = Start-Process -FilePath $makeappxPath -ArgumentList $MakeAppxParmas -PassThru -Wait -WindowStyle Hidden
1054 |
1055 | If($process.exitcode -ne 0){
1056 | write-host $makeappxPath
1057 | write-host $MakeAppxParmas
1058 | throw
1059 | }
1060 |
1061 | Remove-Item -Force -Path $ExtractPath -Recurse
1062 |
1063 | If($pfxPath -and $Password){
1064 | If($TimeStampServer){
1065 | $SignArguments = "sign -f ""$pfxPath"" -p $Password -t ""$TimeStampServer"" -fd SHA256 -v ""$NewMSIXPath"""
1066 | }
1067 | else{
1068 | $SignArguments = "sign -f ""$pfxPath"" -p $Password -fd SHA256 -v ""$NewMSIXPath"""
1069 | }
1070 |
1071 | $process = Start-Process -FilePath $SignTool -ArgumentList ($SignArguments) -PassThru -Wait -WindowStyle Hidden
1072 |
1073 | If($process.exitcode -ne 0){
1074 | write-host $SignTool
1075 | write-host $SignArguments
1076 | throw
1077 | }
1078 | #Check if the Name contians __ folowed by 13 charachters because then that would be the oldpublisherID
1079 | If($ExtractFolderName.Length - $ExtractFolderName.LastIndexOf("__") -2 -eq 13){
1080 | #Install to get the Publisher ID and rename the file. After that uninstall it again
1081 |
1082 | try{
1083 | $OldPublisherID = $ExtractFolderName.Substring($ExtractFolderName.LastIndexOf("__")+2, $ExtractFolderName.Length - $ExtractFolderName.LastIndexOf("__")-2)
1084 |
1085 | $Package = get-item $NewMSIXPath
1086 |
1087 | $AppxPackagesBefore = get-AppxPackage
1088 | Add-AppxPackage -Path $package.Fullname -ErrorAction Stop
1089 | $AppxPackagesAfter = get-AppxPackage
1090 | $Difference = Compare-Object -ReferenceObject $AppxPackagesBefore -DifferenceObject $AppxPackagesAfter
1091 |
1092 | If($Difference.InputObject.count -gt 0){
1093 |
1094 | $NewPublisherId = $Difference.InputObject.PublisherId
1095 |
1096 | Rename-Item -path $NewMSIXPath -NewName ($ExtractFolderName.Replace($OldPublisherID,$NewPublisherId)+".msix")
1097 |
1098 | try{
1099 | $Difference.InputObject | Remove-AppxPackage -ErrorAction Stop
1100 |
1101 | $WPFTextBox_Messages.Text = ("Removed MSIX " +$package.Name)
1102 | $WPFTextBox_Messages.Foreground = "Black"
1103 |
1104 | }catch{
1105 | $ErrorMessage = $_.Exception.Message
1106 |
1107 | $WPFTextBox_Messages.Text = ("Failed to remove package " +$package.Name +" / $ErrorMessage")
1108 | $WPFTextBox_Messages.Foreground = "Red"
1109 |
1110 | $VBS.popup(("Failed to remove MSIX " +$package.Name +"`n`n$ErrorMessage"),0,"Error",16)
1111 | }
1112 | }
1113 | else{
1114 | $WPFTextBox_Messages.Text = ("I think the MSIX " +$package.Name +" was already installed")
1115 | $WPFTextBox_Messages.Foreground = "Black"
1116 |
1117 | $VBS.popup(("I think the MSIX " +$package.Name +" was already installed"),0,"OK",64)
1118 | }
1119 | }catch{
1120 |
1121 | If($ModificationPackagePublisher.Length -gt 2){
1122 |
1123 | $WPFTextBox_Messages.Text = ("Failed to add MSIX " +$package.Name +" it seams to be a Modification Package / $ErrorMessage")
1124 | $WPFTextBox_Messages.Foreground = "Red"
1125 | $VBS.popup(($package.Name +"`nIs a Modification Package. I couldn't automatically change the publisher hash in the Filename.`nYou need to change it manually."),0,"Modification Package",48)
1126 | }
1127 | else{
1128 |
1129 | $ErrorMessage = $_.Exception.Message
1130 | $WPFTextBox_Messages.Text = ("Failed to add MSIX " +$package.Name +" / $ErrorMessage")
1131 | $WPFTextBox_Messages.Foreground = "Red"
1132 |
1133 | $VBS.popup(("Failed to add MSIX " +$package.Name +"`n`n$ErrorMessage"),0,"Error",16)
1134 | }
1135 | }
1136 | }
1137 | }
1138 | }catch{
1139 | $ErrorMessage = $_.Exception.Message
1140 |
1141 | $WPFTextBox_Messages.Text = ("Failed to changed the signature for package " +$package.Name +" / $ErrorMessage")
1142 | $WPFTextBox_Messages.Foreground = "Red"
1143 | return
1144 | }
1145 | }
1146 |
1147 | $WPFTextBox_Messages.Text = ("Change the signature for all selected " +$SelctedPackages.count +" packages.")
1148 | $WPFTextBox_Messages.Foreground = "Black"
1149 |
1150 | explorer.exe $NewMSIXFolder
1151 | }
1152 | else{
1153 | $WPFTextBox_Messages.Text = ("File or Folder not found $CleandUpPath")
1154 | $WPFTextBox_Messages.Foreground = "Red"
1155 | }
1156 |
1157 | Remove-Item -Force -Path $MsixPackagingToolSDK -Recurse
1158 | }
1159 | else{
1160 | $WPFTextBox_Messages.Text = ("Failed to find the MSXI Packaging Tool. For this functionality it is required. Pleas install it from the Windows Store.")
1161 | $WPFTextBox_Messages.Foreground = "Red"
1162 | }
1163 | }else{
1164 | $WPFTextBox_Messages.Text = ("No pfx cert and password, therefore I don’t need to modify anything.")
1165 | $WPFTextBox_Messages.Foreground = "Red"
1166 | }
1167 | }
1168 |
1169 | Function Disable-AutomaticStoreAppUpdates{
1170 |
1171 | $Name = "AutoDownload"
1172 | $Value = 2
1173 | $Path = "HKLM:\SOFTWARE\Policies\Microsoft\WindowsStore"
1174 |
1175 | If($UserIsAdmin -eq $true){
1176 | #Disable Services
1177 |
1178 | try{
1179 |
1180 | If ((Test-Path $Path) -eq $false){
1181 | New-Item -Path $Path -ItemType Directory
1182 | }
1183 |
1184 | If (-!(Get-ItemProperty -Path $Path -Name $name -ErrorAction SilentlyContinue)){
1185 | New-ItemProperty -Path $Path -Name $Name -PropertyType DWord -Value $Value
1186 | }
1187 | else{
1188 | Set-ItemProperty -Path $Path -Name $Name -Value $Value
1189 | }
1190 |
1191 | $WPFTextBox_Messages.Text = "Disabled automatic Updates of Windows Store Apps.”
1192 | $WPFTextBox_Messages.Foreground = "Black"
1193 |
1194 | }
1195 | catch{
1196 | $WPFTextBox_Messages.Text = ("Failed to disable automatic Updates of Windows Store Apps.")
1197 | $WPFTextBox_Messages.Foreground = "Red"
1198 | }
1199 | }
1200 | else{
1201 | $WPFTextBox_Messages.Text = "You are not an administrator and this functionality requires admin rights.”
1202 | $WPFTextBox_Messages.Foreground = "Red"
1203 | }
1204 | }
1205 |
1206 | Function Stop-Services {
1207 |
1208 | #List Of Services to stopp and disable
1209 | $StoppedServices = "none"
1210 | $FailedServices = "none"
1211 | $NotFoundServices = "none"
1212 | $Services = @("PLRestartMgrService","DPS","CscService","WSearch","wuauserv","CcmExec")
1213 |
1214 |
1215 | If($UserIsAdmin -eq $true){
1216 | #Disable Services
1217 |
1218 | ForEach ($Service in $Services){
1219 | $IsAvailable = $null
1220 | $IsAvailable = Get-service $Service -ErrorAction SilentlyContinue
1221 | If($IsAvailable){
1222 | try{
1223 | If($IsAvailable.Status -eq "Running"){
1224 | Stop-Service -Name $Service -Force -ErrorAction Stop
1225 | }
1226 | Set-Service –Name $Service –StartupType "Disabled" -ErrorAction Stop
1227 |
1228 | If($StoppedServices -ne "none"){
1229 | $StoppedServices += (", " +$IsAvailable.DisplayName)
1230 | }
1231 | else{
1232 | $StoppedServices = $IsAvailable.DisplayName.ToString()
1233 | }
1234 | }
1235 | catch{
1236 | If($FailedServices -ne "none"){
1237 | $FailedServices += (", " +$IsAvailable.DisplayName)
1238 | }
1239 | else{
1240 | $FailedServices = $IsAvailable.DisplayName.ToString()
1241 | }
1242 | }
1243 | }
1244 | else{
1245 | If($NotFoundServices -ne "none"){
1246 | $NotFoundServices += (", " +$Service)
1247 | }
1248 | else{
1249 | $NotFoundServices = $Service
1250 | }
1251 | }
1252 | }
1253 |
1254 | $Message = "Stopped those Services: $StoppedServices / Couldn't find those: $NotFoundServices / Failed to stop those: $FailedServices"
1255 | $WPFTextBox_Messages.Text = $Message
1256 |
1257 | If($FailedServices -ne "none"){
1258 | $WPFTextBox_Messages.Foreground = "Red"
1259 | }
1260 | else{
1261 | $WPFTextBox_Messages.Foreground = "Black"
1262 | }
1263 | }
1264 | else{
1265 | $WPFTextBox_Messages.Text = "You are not an administrator and this functionality requires admin rights.”
1266 | $WPFTextBox_Messages.Foreground = "Red"
1267 | }
1268 | }
1269 |
1270 | Function Edit-Manifest {
1271 |
1272 | param(
1273 | [Parameter(Mandatory=$true)]
1274 | [String]
1275 | $Path
1276 | )
1277 |
1278 | $VBS = new-object -comobject wscript.shell
1279 |
1280 |
1281 | $RegExForBuild = "(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])(\.(0|[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])){3}"
1282 | $CleandUpPath = $Path.replace('"',"")
1283 |
1284 | $pfxPath = $WPFTextBox_EditManifest_SelectedCert.Text
1285 | $Password = $WPFPasswordBox_EditManifest_CertPassword.Password
1286 |
1287 | $TimeStampServer = $WPFTextBox_Timeserver.Text
1288 |
1289 | $NewMaxVersionTested = $WPFTextBox_MaxVersionTested.Text
1290 | $NewMinVersionTested = $WPFTextBox_MinVersionTested.Text
1291 |
1292 |
1293 | If(($NewMaxVersionTested) -or ($NewMinVersionTested)){
1294 | #Check if Versionnumbers are Build numbers
1295 | If(($NewMinVersionTested -match $RegExForBuild) -eq $false){
1296 | $WPFTextBox_Messages.Text = ("$NewMinVersionTested is not a regular Buildnumber like 1.0.0.0")
1297 | $WPFTextBox_Messages.Foreground = "Red"
1298 | Return
1299 | }
1300 |
1301 | If(($NewMaxVersionTested -match $RegExForBuild) -eq $false){
1302 | $WPFTextBox_Messages.Text = ("$NewMaxVersionTested is not a regular Buildnumber like 1.0.0.0")
1303 | $WPFTextBox_Messages.Foreground = "Red"
1304 | Return
1305 | }
1306 |
1307 | #Get the SDK Tools
1308 | $MSIXPackagingToolInstallLocation = (Get-AppxPackage -Name "Microsoft.MsixPackagingTool*").InstallLocation
1309 |
1310 | If($MSIXPackagingToolInstallLocation){
1311 |
1312 | $MsixPackagingToolSDK = "$env:TEMP\MsixPackagingToolSDK"
1313 | Copy-Item -Path "$MSIXPackagingToolInstallLocation\SDK" -Destination $MsixPackagingToolSDK -Recurse -Force
1314 |
1315 | $makeappxPath = "$MsixPackagingToolSDK\makeappx.exe"
1316 | $SignTool = "$MsixPackagingToolSDK\signtool.exe"
1317 |
1318 | $NewMSIXFolder = "$env:TEMP\_NewMSIXFiles\"
1319 |
1320 | IF(Test-Path -Path $CleandUpPath){
1321 | If((get-item -Path $CleandUpPath).Extension.ToUpper() -eq ".MSIX"){
1322 | $SelctedPackages = get-item -Path $CleandUpPath
1323 | }
1324 | else{
1325 | $SelctedPackages = (Get-ChildItem -Path $CleandUpPath -Recurse -Filter "*.msix" ) | Sort-Object
1326 | }
1327 |
1328 | ForEach($package in $SelctedPackages){
1329 |
1330 | try{
1331 |
1332 | $SelectedMSIX = get-item -path $package.fullname
1333 |
1334 | $ExtractFolderName = $SelectedMSIX.Name.Replace($SelectedMSIX.Extension,"")
1335 |
1336 | $ExtractPath = "$env:TEMP\$ExtractFolderName"
1337 |
1338 | If(Test-Path -Path $ExtractPath){
1339 | Remove-Item -Force -Path $ExtractPath -Recurse
1340 | }
1341 |
1342 | $UnpackParmas ="unpack -v -d ""$ExtractPath"" -p ""$SelectedMSIX"" -o"
1343 |
1344 |
1345 | #Extract MSIX
1346 | $process = Start-Process -FilePath $makeappxPath -ArgumentList $UnpackParmas -Wait -WindowStyle Hidden -PassThru
1347 |
1348 | If($process.exitcode -ne 0){
1349 | write-host $makeappxPath
1350 | write-host $UnpackParmas
1351 | throw
1352 | }
1353 |
1354 | $ManifestXMLPath = "$ExtractPath\AppxManifest.xml"
1355 |
1356 | $ManifestContent = [XML](Get-Content -Path $ManifestXMLPath)
1357 |
1358 | $MSIXVersionOld = $ManifestContent.Package.Identity.Version
1359 |
1360 |
1361 | If($WPFRadioButton_EditManifest_IncreaseVersion_Yes.IsChecked){
1362 | $MSIXVersionNew = $MSIXVersionOld.split(".")[0] +"." + $MSIXVersionOld.split(".")[1] +"." + $MSIXVersionOld.split(".")[2] +"." +([INT]$MSIXVersionOld.split(".")[3] +1)
1363 | #Set Increased Version
1364 | $ManifestContent.Package.Identity.Version = $MSIXVersionNew
1365 | $NewMSIXName = $ExtractFolderName.Replace($MSIXVersionOld,$MSIXVersionNew)
1366 | }
1367 | else{
1368 | $NewMSIXName = $ExtractFolderName
1369 | }
1370 |
1371 |
1372 | #Change MaxVersionTested and Minversion
1373 | If($NewMaxVersionTested){
1374 | $ManifestContent.Package.Dependencies.TargetDeviceFamily.MaxVersionTested = $NewMaxVersionTested
1375 | }
1376 |
1377 | If($NewMinVersionTested){
1378 | $ManifestContent.Package.Dependencies.TargetDeviceFamily.MinVersion = $NewMinVersionTested
1379 | }
1380 |
1381 | If(($pfxPath) -and ($Password)){
1382 | $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
1383 | $cert.Import($pfxPath,$Password,'DefaultKeySet')
1384 |
1385 | $NewPublisher = $cert.Subject
1386 | $OldPublisher = $ManifestContent.Package.Identity.Publisher
1387 |
1388 | If($OldPublisher -ne $NewPublisher){
1389 |
1390 | $Answer = $VBS.popup(($SelectedMSIX.Name +"`n`n" +"You are not using the same certificate that the one the original package was signed with.`n`nIf you use this certificate the package will be treated as a new package. This means that Updates and Modification Packages will no longer work.`n`nIt’s heavily recommended to use the original certificate and now click on No. `n`nDo you want to use this new certificate anyways and ignore this warning?"),0,"Publisher certificate is different",36)
1391 |
1392 | #7 means the user pressed No, so the modification failes
1393 | If($Answer -eq 7){
1394 | throw
1395 | }
1396 |
1397 | $ManifestContent.Package.Identity.Publisher = $NewPublisher
1398 | }
1399 | }
1400 |
1401 | #Save NewXML
1402 | $ManifestContent.Save($ManifestXMLPath)
1403 |
1404 | If((Test-Path $NewMSIXFolder) -eq $false){
1405 | md $NewMSIXFolder
1406 | }
1407 |
1408 | $NewMSIXPath = "$NewMSIXFolder\$NewMSIXName.msix"
1409 |
1410 | $MakeAppxParmas ="pack -d ""$ExtractPath"" -p ""$NewMSIXPath"" -o"
1411 |
1412 | $process = Start-Process -FilePath $makeappxPath -ArgumentList $MakeAppxParmas -PassThru -Wait -WindowStyle Hidden
1413 |
1414 | If($process.exitcode -ne 0){
1415 | write-host $makeappxPath
1416 | write-host $MakeAppxParmas
1417 | throw
1418 | }
1419 |
1420 | # Remove-Item -Force -Path $ExtractPath -Recurse
1421 |
1422 | If($pfxPath -and $Password){
1423 | If($TimeStampServer){
1424 | $SignArguments = "sign -f ""$pfxPath"" -p $Password -t ""$TimeStampServer"" -fd SHA256 -v ""$NewMSIXPath"""
1425 | }
1426 | else{
1427 | $SignArguments = "sign -f ""$pfxPath"" -p $Password -fd SHA256 -v ""$NewMSIXPath"""
1428 | }
1429 |
1430 | $process = Start-Process -FilePath $SignTool -ArgumentList ($SignArguments) -PassThru -Wait -WindowStyle Hidden
1431 |
1432 | If($process.exitcode -ne 0){
1433 | write-host $SignTool
1434 | write-host $SignArguments
1435 | throw
1436 | }
1437 | }
1438 | }catch{
1439 | $ErrorMessage = $_.Exception.Message
1440 |
1441 | $WPFTextBox_Messages.Text = ("Failed to edit manifest for package " +$package.Name +" / $ErrorMessage")
1442 | $WPFTextBox_Messages.Foreground = "Red"
1443 | return
1444 | }
1445 |
1446 | }
1447 |
1448 | $WPFTextBox_Messages.Text = ("All selected " +$SelctedPackages.count +" Packages are edited.")
1449 | $WPFTextBox_Messages.Foreground = "Black"
1450 |
1451 | explorer.exe $NewMSIXFolder
1452 | }
1453 | else{
1454 | $WPFTextBox_Messages.Text = ("File or Folder not found $CleandUpPath")
1455 | $WPFTextBox_Messages.Foreground = "Red"
1456 | }
1457 |
1458 | Remove-Item -Force -Path $MsixPackagingToolSDK -Recurse
1459 | }
1460 | else{
1461 | $WPFTextBox_Messages.Text = ("Failed to find the MSXI Packaging Tool. For this functionality it is required. Pleas install it from the Windows Store.")
1462 | $WPFTextBox_Messages.Foreground = "Red"
1463 | }
1464 | }else{
1465 | $WPFTextBox_Messages.Text = ("No new MinVersionTested or MaxVersionTested specified, therefore I don’t need to modify anything.")
1466 | $WPFTextBox_Messages.Foreground = "Orange"
1467 |
1468 | }
1469 |
1470 | }
1471 |
1472 | Function Install-PackagingToolDriver{
1473 |
1474 | try{
1475 | $PackagingToolDriver = Get-WindowsCapability -Online | where Name -Like "Msix.PackagingTool.Driver*"
1476 |
1477 |
1478 | $Name = $PackagingToolDriver.Name
1479 | $State = $PackagingToolDriver.State
1480 |
1481 | If($State -eq "NotPresent"){
1482 |
1483 | Add-WindowsCapability -Online -Name $Name -ErrorAction Stop
1484 |
1485 | $WPFTextBox_Messages.Text = ("Installed $Name")
1486 | $WPFTextBox_Messages.Foreground = "Black"
1487 | }
1488 | else{
1489 | $WPFTextBox_Messages.Text = ("The $Name state is already $State")
1490 | $WPFTextBox_Messages.Foreground = "DarkOrange"
1491 | }
1492 | }
1493 | catch{
1494 | $ErrorMessage = $_.Exception.Message
1495 | $WPFTextBox_Messages.Text = ("Couldn't install the PackagingToolDriver / $ErrorMessage")
1496 | $WPFTextBox_Messages.Foreground = "Red"
1497 | }
1498 | }
1499 |
1500 | Function Uninstall-PackagingToolDriver{
1501 |
1502 | try{
1503 | $PackagingToolDriver = Get-WindowsCapability -Online | where Name -Like "Msix.PackagingTool.Driver*"
1504 |
1505 |
1506 | $Name = $PackagingToolDriver.Name
1507 | $State = $PackagingToolDriver.State
1508 |
1509 | If($State -eq "Installed"){
1510 | Remove-WindowsCapability -Online -Name $Name -ErrorAction Stop
1511 |
1512 | $WPFTextBox_Messages.Text = ("Uninstalled $Name")
1513 | $WPFTextBox_Messages.Foreground = "Black"
1514 | }
1515 | else{
1516 | $WPFTextBox_Messages.Text = ("The $Name state is already $State")
1517 | $WPFTextBox_Messages.Foreground = "DarkOrange"
1518 | }
1519 | }
1520 | catch{
1521 | $ErrorMessage = $_.Exception.Message
1522 | $WPFTextBox_Messages.Text = ("Couldn't uninstall the PackagingToolDriver / $ErrorMessage")
1523 | $WPFTextBox_Messages.Foreground = "Red"
1524 | }
1525 | }
1526 |
1527 | Function Get-PackagingToolDriverStatus{
1528 |
1529 |
1530 | try{
1531 | $PackagingToolDriver = Get-WindowsCapability -Online | where Name -Like "Msix.PackagingTool.Driver*"
1532 |
1533 |
1534 | $Name = $PackagingToolDriver.Name
1535 | $State = $PackagingToolDriver.State
1536 |
1537 | $WPFTextBox_Messages.Text = ("The state of $Name is $State")
1538 | $WPFTextBox_Messages.Foreground = "Black"
1539 |
1540 |
1541 | }
1542 | catch{
1543 | $ErrorMessage = $_.Exception.Message
1544 | $WPFTextBox_Messages.Text = ("Couldn't get the state / $ErrorMessage")
1545 | $WPFTextBox_Messages.Foreground = "Red"
1546 | }
1547 |
1548 | }
1549 |
1550 | Function Install-MSIX {
1551 |
1552 | param(
1553 | [Parameter(Mandatory=$true)]
1554 | [String]
1555 | $Path
1556 | )
1557 |
1558 | $CleandUpPath = $Path.replace('"',"")
1559 |
1560 | IF(Test-Path -Path $CleandUpPath){
1561 |
1562 | If((get-item -Path $CleandUpPath).Extension.ToUpper() -eq ".MSIX"){
1563 | $package = get-item -Path $CleandUpPath
1564 |
1565 | try{
1566 | Add-AppxPackage -Path $package.Fullname -ErrorAction Stop
1567 |
1568 | $WPFTextBox_Messages.Text = ("Added package " +$package.Name)
1569 | $WPFTextBox_Messages.Foreground = "Black"
1570 |
1571 | }catch{
1572 | $ErrorMessage = $_.Exception.Message
1573 |
1574 | $WPFTextBox_Messages.Text = ("Failed to add package " +$package.Name +" / $ErrorMessage")
1575 | $WPFTextBox_Messages.Foreground = "Red"
1576 | }
1577 | }
1578 | else{
1579 | $WPFTextBox_Messages.Text = ("The File seams not to be an MSIX $CleandUpPath")
1580 | $WPFTextBox_Messages.Foreground = "Red"
1581 | }
1582 | }
1583 | else{
1584 | $WPFTextBox_Messages.Text = ("File not found $CleandUpPath")
1585 | $WPFTextBox_Messages.Foreground = "Red"
1586 | }
1587 |
1588 |
1589 | }
1590 |
1591 | Function Test-MSIX {
1592 |
1593 | param(
1594 | [Parameter(Mandatory=$true)]
1595 | [String]
1596 | $Path
1597 | )
1598 | $VBS = new-object -comobject wscript.shell
1599 |
1600 | $CleandUpPath = $Path.replace('"',"")
1601 |
1602 | IF(Test-Path -Path $CleandUpPath){
1603 |
1604 |
1605 | If((get-item -Path $CleandUpPath).Extension.ToUpper() -eq ".MSIX"){
1606 | $FoundPackages = get-item -Path $CleandUpPath
1607 | }
1608 | else{
1609 | $FoundPackages = (Get-ChildItem -Path $CleandUpPath -Recurse -Filter "*.msix" ) | Sort-Object
1610 | }
1611 |
1612 |
1613 | If($FoundPackages.count -ne 1){
1614 | $WPFTextBox_Messages.Text = ("In the new window, select all the MSIX packages you want to test")
1615 | $WPFTextBox_Messages.Foreground = "Black"
1616 |
1617 | $SelctedPackages = $FoundPackages | Select-Object -Property Name,FullName |Out-GridView -Title ("Select MSIX files you want to test ("+$FoundPackages.count+")" )-OutputMode Multiple
1618 | }
1619 | else{
1620 | $SelctedPackages = $FoundPackages
1621 | }
1622 |
1623 | ForEach($package in $SelctedPackages){
1624 | $Message = ""
1625 |
1626 | try{
1627 | $AppxPackagesBefore = get-AppxPackage
1628 | Add-AppxPackage -Path $package.Fullname -ErrorAction Stop
1629 | $AppxPackagesAfter = get-AppxPackage
1630 | $Difference = Compare-Object -ReferenceObject $AppxPackagesBefore -DifferenceObject $AppxPackagesAfter
1631 |
1632 | If($Difference.InputObject.count -gt 0){
1633 |
1634 | $ManifestPath = ($Difference.InputObject.InstallLocation +"\AppxManifest.xml")
1635 |
1636 | [xml]$ManifestContent = Get-Content -Path $ManifestPath
1637 |
1638 |
1639 | $Applications = $ManifestContent.Package.Applications.Application
1640 |
1641 | ForEach($Application in $Applications){
1642 | [String]$Message += ("`n - " + $Application.VisualElements.DisplayName)
1643 | }
1644 |
1645 | $WPFTextBox_Messages.Text = ("Added MSIX " +$package.Name)
1646 | $WPFTextBox_Messages.Foreground = "Black"
1647 |
1648 | $VBS.popup(("Added MSIX " +$package.Name +" `n`nReady for Test. `n`nThe following things changed in the Startmenu: `n" +$Message),0,"OK",64)
1649 | $VBS.popup(("Only klick on OK when your done testing " +$package.Name +"`nIt will be uninstalled now!"),0,"OK",64)
1650 |
1651 | try{
1652 | $Difference.InputObject | Remove-AppxPackage -ErrorAction Stop
1653 |
1654 | $WPFTextBox_Messages.Text = ("Removed MSIX " +$package.Name)
1655 | $WPFTextBox_Messages.Foreground = "Black"
1656 |
1657 | $VBS.popup(("Removed MSIX " +$package.Name),0,"OK",64)
1658 |
1659 | }catch{
1660 | $ErrorMessage = $_.Exception.Message
1661 |
1662 | $WPFTextBox_Messages.Text = ("Failed to remove package " +$package.Name +" / $ErrorMessage")
1663 | $WPFTextBox_Messages.Foreground = "Red"
1664 |
1665 | $VBS.popup(("Failed to remove MSIX " +$package.Name +"`n`n$ErrorMessage"),0,"Error",16)
1666 | }
1667 |
1668 | }
1669 | else{
1670 |
1671 | $WPFTextBox_Messages.Text = ("I think the MSIX " +$package.Name +" was already installed")
1672 | $WPFTextBox_Messages.Foreground = "Black"
1673 |
1674 | $VBS.popup(("I think the MSIX " +$package.Name +" was already installed"),0,"OK",64)
1675 | }
1676 |
1677 | }catch{
1678 | $ErrorMessage = $_.Exception.Message
1679 |
1680 | $WPFTextBox_Messages.Text = ("Failed to add MSIX " +$package.Name +" / $ErrorMessage")
1681 | $WPFTextBox_Messages.Foreground = "Red"
1682 |
1683 | $VBS.popup(("Failed to add MSIX " +$package.Name +"`n`n$ErrorMessage"),0,"Error",16)
1684 | }
1685 |
1686 | }
1687 |
1688 | $WPFTextBox_Messages.Text = ("All selected " +$SelctedPackages.count +" Packages are done.")
1689 | $WPFTextBox_Messages.Foreground = "Black"
1690 | }
1691 | else{
1692 | $WPFTextBox_Messages.Text = ("File or Folder not found $CleandUpPath")
1693 | $WPFTextBox_Messages.Foreground = "Red"
1694 | }
1695 |
1696 | }
1697 |
1698 | Function Start-App{
1699 | $SelectedMSIX = $null
1700 | $SelectedMSIX = $WPFListView_MSIXPackages.SelectedItem.Name
1701 | $SelectedMSIXInstallLocation= $WPFListView_MSIXPackages.SelectedItem.InstallLocation
1702 | $SelectedMSIXInstallLocation= $WPFListView_MSIXPackages.SelectedItem.InstallLocation
1703 | $SelectedMSIXManifest = "$SelectedMSIXInstallLocation\AppxManifest.xml"
1704 |
1705 | If($MSIXData){
1706 | IF($SelectedMSIX){
1707 | $WPFTextBox_Messages.Text = "The selected MSIX is $SelectedMSIX"
1708 | $WPFTextBox_Messages.Foreground = "Black"
1709 |
1710 | [XML]$SelectedMSIXManifestContent = Get-Content $SelectedMSIXManifest
1711 | $ApplicationIDs = ($SelectedMSIXManifestContent.Package.Applications.Application).id
1712 |
1713 |
1714 | If($ApplicationIDs.count -le 1){
1715 | try{
1716 | ForEach($ApplicationID in $ApplicationIDs){
1717 | explorer.exe shell:AppsFolder\$(get-appxpackage -name $SelectedMSIX | select -expandproperty PackageFamilyName)!$ApplicationID
1718 | }
1719 | $WPFTextBox_Messages.Text = "Startet the Apps from the MSIX $SelectedMSIX"
1720 | $WPFTextBox_Messages.Foreground = "Black"
1721 | }
1722 | catch{
1723 | $ErrorMessage = $_.Exception.Message
1724 |
1725 | $WPFTextBox_Messages.Text ="Failed to Start the Apps from $SelectedMSIX / $ErrorMessage"
1726 | $WPFTextBox_Messages.Foreground = "RED"
1727 | }
1728 | }
1729 | else{
1730 | $WPFTextBox_Messages.Text = "Found no Application ID's in the $SelectedMSIXManifest"
1731 | $WPFTextBox_Messages.Foreground = "RED"
1732 | }
1733 | }
1734 | else{
1735 | $WPFTextBox_Messages.Text = "You need to select a MSIX first"
1736 | $WPFTextBox_Messages.Foreground = "Black"
1737 | }
1738 | }
1739 | else{
1740 | $WPFTextBox_Messages.Text = "You need to get the Software first and then select an MSIX!"
1741 | $WPFTextBox_Messages.Foreground = "Black"
1742 | }
1743 |
1744 | }
1745 |
1746 | Function uninstall-App{
1747 | $SelectedMSIX = $null
1748 | $SelectedMSIX = $WPFListView_MSIXPackages.SelectedItem.Name
1749 | $SelectedMSIXInstallLocation= $WPFListView_MSIXPackages.SelectedItem.InstallLocation
1750 |
1751 | If($MSIXData){
1752 | IF($SelectedMSIX){
1753 | $WPFTextBox_Messages.Text = "The selected MSIX is $SelectedMSIX"
1754 | $WPFTextBox_Messages.Foreground = "Black"
1755 | try{
1756 | Get-AppxPackage | where InstallLocation -EQ $SelectedMSIXInstallLocation | Remove-AppxPackage
1757 | Get-InstalledMSIX
1758 | Use-Filter
1759 | $WPFTextBox_Messages.Text = "Uninstalled the MSIX $SelectedMSIX"
1760 | $WPFTextBox_Messages.Foreground = "Black"
1761 | }
1762 | catch{
1763 | $ErrorMessage = $_.Exception.Message
1764 |
1765 | $WPFTextBox_Messages.Text ="Failed to uninstall the App $SelectedMSIX / $ErrorMessage"
1766 | $WPFTextBox_Messages.Foreground = "RED"
1767 | }
1768 | }
1769 | else{
1770 | $WPFTextBox_Messages.Text = "You need to select a MSIX first"
1771 | $WPFTextBox_Messages.Foreground = "Black"
1772 | }
1773 | }
1774 | else{
1775 | $WPFTextBox_Messages.Text = "You need to get the Software first and then select an MSIX!"
1776 | $WPFTextBox_Messages.Foreground = "Black"
1777 | }
1778 |
1779 | }
1780 |
1781 | Function Open-UserData{
1782 | $SelectedMSIX = $null
1783 | $SelectedMSIX = $WPFListView_MSIXPackages.SelectedItem.Name
1784 | $SelectedMSIXInstallLocation= $WPFListView_MSIXPackages.SelectedItem.InstallLocation
1785 |
1786 | $SelectedMSIXInstallPublisherHash = $SelectedMSIXInstallLocation.Substring($SelectedMSIXInstallLocation.LastIndexOf("_")+1,$SelectedMSIXInstallLocation.Length -$SelectedMSIXInstallLocation.LastIndexOf("_")-1)
1787 | $UserDataLocation = "$env:LOCALAPPDATA\Packages\$SelectedMSIX"+"_"+$SelectedMSIXInstallPublisherHash
1788 |
1789 |
1790 | If($MSIXData){
1791 | IF($SelectedMSIX){
1792 | $WPFTextBox_Messages.Text = "The selected MSIX is $UserDataLocation"
1793 | $WPFTextBox_Messages.Foreground = "Black"
1794 | explorer.exe $UserDataLocation
1795 |
1796 |
1797 | }
1798 | else{
1799 | $WPFTextBox_Messages.Text = "You need to select a MSIX first"
1800 | $WPFTextBox_Messages.Foreground = "Black"
1801 | }
1802 | }
1803 | else{
1804 | $WPFTextBox_Messages.Text = "You need to get the Software first and then select an MSIX!"
1805 | $WPFTextBox_Messages.Foreground = "Black"
1806 | }
1807 | }
1808 |
1809 | Function Open-Manifest{
1810 | $SelectedMSIX = $null
1811 | $SelectedMSIX = $WPFListView_MSIXPackages.SelectedItem.Name
1812 | $SelectedMSIXInstallLocation= $WPFListView_MSIXPackages.SelectedItem.InstallLocation
1813 |
1814 | If($MSIXData){
1815 | IF($SelectedMSIX){
1816 | $WPFTextBox_Messages.Text = "The selected MSIX is $SelectedMSIX"
1817 | $WPFTextBox_Messages.Foreground = "Black"
1818 | explorer.exe "$SelectedMSIXInstallLocation\AppxManifest.xml"
1819 |
1820 |
1821 | }
1822 | else{
1823 | $WPFTextBox_Messages.Text = "You need to select a MSIX first"
1824 | $WPFTextBox_Messages.Foreground = "Black"
1825 | }
1826 | }
1827 | else{
1828 | $WPFTextBox_Messages.Text = "You need to get the Software first and then select an MSIX!"
1829 | $WPFTextBox_Messages.Foreground = "Black"
1830 | }
1831 |
1832 | }
1833 |
1834 | Function Open-InstallLocation{
1835 | $SelectedMSIX = $null
1836 | $SelectedMSIX = $WPFListView_MSIXPackages.SelectedItem.Name
1837 | $SelectedMSIXInstallLocation= $WPFListView_MSIXPackages.SelectedItem.InstallLocation
1838 |
1839 | If($MSIXData){
1840 | IF($SelectedMSIX){
1841 | $WPFTextBox_Messages.Text = "The selected MSIX is $SelectedMSIX"
1842 | $WPFTextBox_Messages.Foreground = "Black"
1843 | explorer.exe $SelectedMSIXInstallLocation
1844 |
1845 |
1846 | }
1847 | else{
1848 | $WPFTextBox_Messages.Text = "You need to select a MSIX first"
1849 | $WPFTextBox_Messages.Foreground = "Black"
1850 | }
1851 | }
1852 | else{
1853 | $WPFTextBox_Messages.Text = "You need to get the Software first and then select an MSIX!"
1854 | $WPFTextBox_Messages.Foreground = "Black"
1855 | }
1856 |
1857 | }
1858 |
1859 | Function Get-InstalledMSIX{
1860 |
1861 | $Script:MSIXData = ""
1862 | $Script:MSIXData = @()
1863 | $InstalledApps = @()
1864 |
1865 |
1866 | If($WPFCheckBox_EnterpriseSigned.IsChecked){
1867 | $InstalledApps += Get-AppxPackage | Where-object SignatureKind -EQ "Developer" |Select-Object -Property Name,Version,Publisher,InstallLocation,Dependencies,PackageFullName
1868 | $InstalledApps += Get-AppxPackage | Where-object SignatureKind -EQ "Enterprise" |Select-Object -Property Name,Version,Publisher,InstallLocation,Dependencies,PackageFullName
1869 |
1870 | }
1871 | else{
1872 |
1873 | $InstalledApps = Get-AppxPackage | Select-Object -Property Name,Version,Publisher,InstallLocation,Dependencies,PackageFullName
1874 |
1875 | }
1876 |
1877 | ForEach($InstalledApp in $InstalledApps){
1878 | $Dependencies = ""
1879 | $DependenciesCount = 0
1880 | $Name = $InstalledApp.Name
1881 | $Publisher = $InstalledApp.Publisher
1882 | $Version = $InstalledApp.Version
1883 | $InstallLocation = $InstalledApp.InstallLocation
1884 | ForEach($Dependencie in $InstalledApp.Dependencies){
1885 | $DependenciesCount = $DependenciesCount +1
1886 | If($DependenciesCount -eq 1){
1887 | $Dependencies = $Dependencie.ToString()
1888 | }else{
1889 | $Dependencies = $Dependencies +" / " +$Dependencie.ToString()
1890 |
1891 | }
1892 | }
1893 |
1894 | $PackageType = 'Appx'
1895 | $HasPsf = $false
1896 | try{
1897 | $mani = Get-AppxPackageManifest -Package $InstalledApp.PackageFullName
1898 | }
1899 | catch{
1900 | }
1901 | $capabilitiesArr = $mani.GetElementsByTagName('Capabilities')
1902 | ForEach($capabilities in $capabilitiesArr)
1903 | {
1904 | $rescapCapabilityArr = $capabilities.GetElementsByTagName('rescap:Capability')
1905 | foreach ($rescapCapability in $rescapCapabilityArr)
1906 | {
1907 | if ($rescapCapability.Name -eq 'runFullTrust')
1908 | {
1909 | $PackageType = 'MSIX (Full Trust)'
1910 | $PsfConfigArr = Get-ChildItem -Filter 'config.json' -recurse -path $InstalledApp.InstallLocation
1911 | if ($PsfConfigArr -ne $null)
1912 | {
1913 | $HasPsf = $true
1914 | }
1915 | }
1916 | }
1917 | $capabilityArr = $capabilities.GetElementsByTagName('Capability')
1918 | foreach ($capability in $capabilityArr)
1919 | {
1920 | #only possible in manually generated manifests
1921 | if ($capability.Name -eq 'runFullTrust')
1922 | {
1923 | $PackageType = 'MSIX (Full Trust)'
1924 | $PsfConfigArr = Get-ChildItem -Filter 'config.json' -recurse -path $InstalledApp.InstallLocation
1925 | if ($PsfConfigArr -ne $null)
1926 | {
1927 | $HasPsf = $true
1928 | }
1929 | }
1930 | }
1931 | }
1932 |
1933 | #$InstallDate = [Datetime]::ParseExact($InstalledSoftware.InstallDate,(Get-culture).DateTimeFormat.ShortDatePattern +" " +(Get-culture).DateTimeFormat.LongTimePattern,$null)
1934 |
1935 | $SoftwareDetail = New-Object PSObject
1936 | $SoftwareDetail | Add-Member -Name "Name" -MemberType NoteProperty -Value $Name
1937 | $SoftwareDetail | Add-Member -Name "Version" -MemberType NoteProperty -Value $Version
1938 | $SoftwareDetail | Add-Member -Name "Publisher" -MemberType NoteProperty -Value $Publisher
1939 | $SoftwareDetail | Add-Member -Name "InstallLocation" -MemberType NoteProperty -Value $InstallLocation
1940 | $SoftwareDetail | Add-Member -Name "PackageType" -MemberType NoteProperty -Value $PackageType
1941 | $SoftwareDetail | Add-Member -Name "HasPsf" -MemberType NoteProperty -Value $HasPsf
1942 | $SoftwareDetail | Add-Member -Name "Dependencies" -MemberType NoteProperty -Value $Dependencies
1943 |
1944 | $Script:MSIXData += $SoftwareDetail
1945 |
1946 |
1947 | }
1948 |
1949 |
1950 | If ($Script:MSIXData.count -gt 1){
1951 | $sortedlist = ($Script:MSIXData | Sort-Object -Property Name)
1952 | }
1953 | else{
1954 | $sortedlist = @($Script:MSIXData,"")
1955 | }
1956 |
1957 |
1958 | $WPFListView_MSIXPackages.ItemsSource = $sortedlist
1959 |
1960 | }
1961 |
1962 | Function Use-Filter{
1963 |
1964 | If($MSIXData){
1965 | If($WPFTexBox_Filter.Text){
1966 | $WPFTextBox_Messages.Text = "Setting filter to " +$WPFTexBox_Filter.Text
1967 | $WPFTextBox_Messages.Foreground = "Black"
1968 |
1969 | }
1970 | else{
1971 | $WPFTextBox_Messages.Text = "Removing Filter"
1972 | $WPFTextBox_Messages.Foreground = "Black"
1973 | }
1974 |
1975 | #Use Filter
1976 | $filter = $WPFTexBox_Filter.Text
1977 | $viewMSIXPackages = [System.Windows.Data.CollectionViewSource]::GetDefaultView($WPFListView_MSIXPackages.ItemsSource)
1978 | $viewMSIXPackages.Filter = {param ($item) $item -match $filter}
1979 |
1980 | $viewMSIXPackages.Refresh()
1981 |
1982 | }
1983 | else{
1984 | $WPFTextBox_Messages.Text = "You need to get the Software first!"
1985 | $WPFTextBox_Messages.Foreground = "Black"
1986 | }
1987 | }
1988 |
1989 | Function Import-CertToTrustedPeopleFromMSIX{
1990 |
1991 | #Check if user is Admin
1992 | If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")) {
1993 | #If he is an Admin
1994 |
1995 |
1996 |
1997 | $MSIXToInstallCertFrom = $WPFTextBox_SelectedCertFromMSIX.Text
1998 | If(-!$MSIXToInstallCertFrom){
1999 | $WPFTextBox_Messages.Text ="No MSIX provided"
2000 | $WPFTextBox_Messages.Foreground = "RED"
2001 | Return
2002 | }
2003 | else{
2004 | If(Test-Path -Path $MSIXToInstallCertFrom){
2005 |
2006 | try{
2007 |
2008 | $CertContent= (Get-AuthenticodeSignature -FilePath $MSIXToInstallCertFrom).SignerCertificate
2009 | $CertToInstall = "$env:temp\temp.cer"
2010 | Export-Certificate -Cert $CertContent -FilePath $CertToInstall -Force
2011 | Import-Certificate -FilePath $CertToInstall -CertStoreLocation cert:\LocalMachine\TrustedPeople
2012 | Remove-Item -Path $CertToInstall -Force
2013 |
2014 | $WPFTextBox_Messages.Text ="Succesfully installed Cert to LocalMachine\TrustedPeople from $MSIXToInstallCertFrom"
2015 | $WPFTextBox_Messages.Foreground = "Black"
2016 |
2017 | }
2018 | catch{
2019 | $ErrorMessage = $_.Exception.Message
2020 |
2021 | $WPFTextBox_Messages.Text ="Failed to install the cert File / $ErrorMessage"
2022 | $WPFTextBox_Messages.Foreground = "RED"
2023 | }
2024 |
2025 | }
2026 | else{
2027 | $WPFTextBox_Messages.Text ="The Path $MSIXToInstallCertFrom is not valid"
2028 | $WPFTextBox_Messages.Foreground = "RED"
2029 | Return
2030 | }
2031 |
2032 | }
2033 | }
2034 | else{
2035 | #If he is NO Admin
2036 | $WPFTextBox_Messages.Text = "You are not an administrator. This Action requieres the tool to be run as an administrator!"
2037 | $WPFTextBox_Messages.Foreground = "Red"
2038 | Return
2039 | }
2040 |
2041 | }
2042 |
2043 | Function Import-CertToTrustedPeople{
2044 |
2045 | #Check if user is Admin
2046 | If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")) {
2047 | #If he is an Admin
2048 | $CertToInstall = $WPFTextBox_SelectedCert.Text
2049 | If(-!$CertToInstall){
2050 | $WPFTextBox_Messages.Text ="No Cert provided"
2051 | $WPFTextBox_Messages.Foreground = "RED"
2052 | Return
2053 | }
2054 | else{
2055 | If(Test-Path -Path $CertToInstall){
2056 |
2057 | try{
2058 | Import-Certificate -FilePath $CertToInstall -CertStoreLocation cert:\LocalMachine\TrustedPeople
2059 | $WPFTextBox_Messages.Text ="Succesfully installed Cert to LocalMachine\TrustedPeople $CertToInstall"
2060 | $WPFTextBox_Messages.Foreground = "Black"
2061 |
2062 | }
2063 | catch{
2064 | $ErrorMessage = $_.Exception.Message
2065 |
2066 | $WPFTextBox_Messages.Text ="Failed to install the cert File / $ErrorMessage"
2067 | $WPFTextBox_Messages.Foreground = "RED"
2068 | }
2069 |
2070 | }
2071 | else{
2072 | $WPFTextBox_Messages.Text ="The Path $CertToInstall is not valid"
2073 | $WPFTextBox_Messages.Foreground = "RED"
2074 | Return
2075 | }
2076 |
2077 | }
2078 | }
2079 | else{
2080 | #If he is NO Admin
2081 | $WPFTextBox_Messages.Text = "You are not an administrator. This Action requieres the tool to be run as an administrator!"
2082 | $WPFTextBox_Messages.Foreground = "Red"
2083 | Return
2084 | }
2085 |
2086 | }
2087 |
2088 | Function Select-Cert{
2089 | $WPFTextBox_SelectedCert.Text = $null
2090 |
2091 | #Select Cer File
2092 | [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
2093 | $OpenFileDialogCER = New-Object System.Windows.Forms.OpenFileDialog
2094 | #$OpenFileDialogCER.initialDirectory = ((get-item $ThisScriptParentPath).Parent).FullName
2095 | $OpenFileDialogCER.filter = "CER (*.cer)| *.cer"
2096 | $OpenFileDialogCER.Title = "Select the Cer File that you want to install"
2097 | $OpenFileDialogCER.ShowDialog() | Out-Null
2098 | $CER= $OpenFileDialogCER.FileName
2099 | $CERFileName = $OpenFileDialogCER.SafeFileName
2100 |
2101 | If($CER){
2102 | If($CERFileName.ToUpper().Contains(".CER") -gt 0){
2103 | $WPFTextBox_SelectedCert.Text = $CER
2104 | $WPFTextBox_Messages.Text = "$CERFileName selected. This is a valid CER-File"
2105 | $WPFTextBox_Messages.Foreground = "Black"
2106 | }
2107 | else{
2108 | $WPFTextBox_Messages.Text = "$CERFileName is not a valid CER-File! Select something else."
2109 | $WPFTextBox_Messages.Foreground = "Red"
2110 | }
2111 | }
2112 | else{
2113 | $WPFTextBox_Messages.Text = "Nothing selected!"
2114 | $WPFTextBox_Messages.Foreground = "Red"
2115 | }
2116 |
2117 | }
2118 |
2119 | Function Creat-SelfSignedCert{
2120 | $YourPublisher = $WPFTextBox_NewCertPublisherName.Text #Name for the Publisher
2121 | $FriendlyName = $WPFTextBox_NewCertFriendlyName.Text #What ever friendly name you like
2122 | $password = $WPFPasswordBox_NewCertPassword.Password #Remember that one, you need it again when creating your MSIX
2123 | $FolderToExportCert = $WPFTextBox_NewCertFolderName.Text #The folder already needs to exist.
2124 | $CertName= $WPFTextBox_NewCertFileName.Text #The Filename your Cert should have
2125 |
2126 |
2127 | If(-!$YourPublisher){
2128 | $WPFTextBox_Messages.Text ="No Publishername provided"
2129 | $WPFTextBox_Messages.Foreground = "RED"
2130 | Return
2131 | }
2132 | else{
2133 | If(-!$YourPublisher.indexof("CN=")-gt 0){
2134 | $YourPublisher = "CN=$YourPublisher"
2135 | }
2136 | }
2137 |
2138 |
2139 | If(-!$FriendlyName){
2140 | $WPFTextBox_Messages.Text ="No Friendlyname provided"
2141 | $WPFTextBox_Messages.Foreground = "RED"
2142 | Return
2143 | }
2144 |
2145 | If(-!$password){
2146 | $WPFTextBox_Messages.Text ="No password provided"
2147 | $WPFTextBox_Messages.Foreground = "RED"
2148 | Return
2149 | }
2150 |
2151 | If(-!$FolderToExportCert){
2152 | $WPFTextBox_Messages.Text ="No Export Folder provided"
2153 | $WPFTextBox_Messages.Foreground = "RED"
2154 | Return
2155 | }
2156 |
2157 | If(-!$CertName){
2158 | $WPFTextBox_Messages.Text ="No Filename provided"
2159 | $WPFTextBox_Messages.Foreground = "RED"
2160 | Return
2161 | }
2162 |
2163 |
2164 | try{
2165 |
2166 | $PFXName= ($FolderToExportCert +'\' +$CertName +'.pfx')
2167 | $CertName= ($FolderToExportCert +'\' +$CertName +'.cer')
2168 |
2169 |
2170 | If(Test-Path $PFXName){
2171 | $WPFTextBox_Messages.Text ="The File $PFXName already exists. I will do nothing. Choose an other name or remove the file first."
2172 | $WPFTextBox_Messages.Foreground = "RED"
2173 | Return
2174 | }
2175 | else{
2176 | If(Test-Path $CertName){
2177 | $WPFTextBox_Messages.Text ="The File $CertName already exists. I will do nothing. Choose an other name or remove the file first."
2178 | $WPFTextBox_Messages.Foreground = "RED"
2179 | Return
2180 | }
2181 | else{
2182 | $cert = New-SelfSignedCertificate -Type Custom -Subject $YourPublisher -KeyUsage DigitalSignature -FriendlyName $FriendlyName -CertStoreLocation 'Cert:\CurrentUser\my'
2183 | $pwd = ConvertTo-SecureString -String $password -Force -AsPlainText
2184 | $cert | Export-PfxCertificate -FilePath $PFXName -Password $pwd
2185 | $cert | Export-Certificate -Type CERT -FilePath $CertName
2186 | remove-item $cert.PSPath
2187 |
2188 | $WPFTextBox_Messages.Text ="Created Certfile $PFXName"
2189 | $WPFTextBox_Messages.Foreground = "Black"
2190 | }
2191 | }
2192 |
2193 | }
2194 | catch{
2195 |
2196 | $ErrorMessage = $_.Exception.Message
2197 |
2198 | $WPFTextBox_Messages.Text ="Failed to creat File $PFXName / $ErrorMessage"
2199 | $WPFTextBox_Messages.Foreground = "RED"
2200 | }
2201 | }
2202 |
2203 | Function Select-Folder{
2204 | Add-Type -AssemblyName System.Windows.Forms
2205 | $FolderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
2206 | [void]$FolderBrowser.ShowDialog()
2207 | $FolderBrowser.SelectedPath
2208 | }
2209 |
2210 | Function Select-MSIX {
2211 |
2212 | #Select MSIX File
2213 | [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
2214 | $OpenFileDialogMSIX = New-Object System.Windows.Forms.OpenFileDialog
2215 | #$OpenFileDialogMSIX.initialDirectory = ((get-item $ThisScriptParentPath).Parent).FullName
2216 | $OpenFileDialogMSIX.filter = "MSIX (*.msix)| *.msix"
2217 | $OpenFileDialogMSIX.Title = "Select the MSIX File that you want to use"
2218 | $OpenFileDialogMSIX.ShowDialog() | Out-Null
2219 | $MSIX= $OpenFileDialogMSIX.FileName
2220 | $MSIXFileName = $OpenFileDialogMSIX.SafeFileName
2221 |
2222 | If($MSIX){
2223 | If($MSIXFileName.ToUpper().Contains(".MSIX") -gt 0){
2224 | $WPFTextBox_Messages.Text = "$MSIXFileName selected. This is a valid MSIX-File"
2225 | $WPFTextBox_Messages.Foreground = "Black"
2226 | $MSIX
2227 | }
2228 | else{
2229 | $WPFTextBox_Messages.Text = "$MSIXFileName is not a valid MSIX-File! Select something else."
2230 | $WPFTextBox_Messages.Foreground = "Red"
2231 | }
2232 | }
2233 | else{
2234 | $WPFTextBox_Messages.Text = "Nothing selected!"
2235 | $WPFTextBox_Messages.Foreground = "Red"
2236 | }
2237 |
2238 |
2239 | }
2240 |
2241 | Function Select-File {
2242 | param(
2243 | [Parameter(Mandatory=$true)]
2244 | [String]
2245 | $FileType
2246 | )
2247 |
2248 | #Select File
2249 | [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
2250 | $OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
2251 | If($FileType.IndexOf(".") -gt 0){
2252 | $OpenFileDialog.filter = "$FileType ($FileType)| $FileType"
2253 |
2254 | }else{
2255 | $OpenFileDialog.filter = "$FileType (*.$FileType)| *.$FileType"
2256 | }
2257 | $OpenFileDialog.Title = "Select the $FileType file that you want to use"
2258 | $OpenFileDialog.ShowDialog() | Out-Null
2259 | $File= $OpenFileDialog.FileName
2260 | $FileName = $OpenFileDialog.SafeFileName
2261 |
2262 | If($File){
2263 | If($FileName.ToUpper().EndsWith($FileType.ToUpper()) -gt 0){
2264 | $WPFTextBox_Messages.Text = "$FileName selected. This is a valid $FileType"
2265 | $WPFTextBox_Messages.Foreground = "Black"
2266 | $File
2267 | }
2268 | else{
2269 | $WPFTextBox_Messages.Text = "$FileName is not a valid $FileType! Select something else."
2270 | $WPFTextBox_Messages.Foreground = "Red"
2271 | }
2272 | }
2273 | else{
2274 | $WPFTextBox_Messages.Text = "Nothing selected!"
2275 | $WPFTextBox_Messages.Foreground = "Red"
2276 | }
2277 |
2278 |
2279 | }
2280 |
2281 | #endregion
2282 |
2283 | #region Initialize
2284 |
2285 | $RunMode = "Script"
2286 | $ThisScriptParentPath = $MyInvocation.MyCommand.Path -replace $myInvocation.MyCommand.Name,""
2287 | $ThisScriptName = $myInvocation.MyCommand.Name
2288 |
2289 | #If the Script gets executed as EXE we need another way to get ThisScriptParentPath
2290 | If(-not($script:ThisScriptParentPath)){
2291 | $Script:ThisScriptParentPath = [System.Diagnostics.Process]::GetCurrentProcess() | Select-Object -ExpandProperty Path | Split-Path
2292 | $RunMode = "EXE"
2293 | }
2294 |
2295 |
2296 | #Set Version
2297 | $WPFLabel_Version.Content = "Version: $ScriptVersion"
2298 |
2299 | #Clear some Stuff First
2300 | $MSIXData =$null
2301 |
2302 | #Check Sideloading Staus
2303 |
2304 | $CurrentSideloadingStaus = Check-SideloadingStaus
2305 |
2306 | $WPFTexBlock_CurrentSideloading_Status.Text = $CurrentSideloadingStaus
2307 |
2308 | If($CurrentSideloadingStaus.Contains("Enabled")){
2309 | $WPFTexBlock_CurrentSideloading_Status.Foreground = "#FF0A7211" #Green
2310 | $WPFButton_Change_SidelaodingStatus.Content = "Disable*"
2311 | }else{
2312 | $WPFTexBlock_CurrentSideloading_Status.Foreground = "#FFFF0600" #Red
2313 | $WPFButton_Change_SidelaodingStatus.Content = "Enable*"
2314 | }
2315 |
2316 |
2317 | #Check if the OS Version is supported
2318 | $OSVersion = (Get-WmiObject -class Win32_OperatingSystem ).Version
2319 |
2320 | [int]$Major = $OSVersion.split(".")[0]
2321 | [int]$Build = $OSVersion.split(".")[2]
2322 |
2323 | If($Major -ge 10){
2324 | If($Build -ge 17763){
2325 | $WPFTextBox_Messages.Text ="Your Windows Version supports all features of this tool."
2326 | $WPFTextBox_Messages.Foreground = "Green"
2327 | }
2328 | ElseIf($Build -eq 17134){
2329 | $WPFTextBox_Messages.Text ="You are running Windows 10 1803. In this version not all features of this tool are working."
2330 | $WPFTextBox_Messages.Foreground = "DarkOrange"
2331 | }
2332 | ElseIf($Build -eq 16299){
2333 | $WPFTextBox_Messages.Text ="You are running Windows 10 1709. In this version not all features of this tool are working."
2334 | $WPFTextBox_Messages.Foreground = "DarkOrange"
2335 | }
2336 | else{
2337 | $WPFTextBox_Messages.Text ="You are running Windows $OSVersion. This tool is not working with your Version of Windows. You need W10 1709 or higer."
2338 | $WPFTextBox_Messages.Foreground = "Red"
2339 | }
2340 | }
2341 | else{
2342 | $WPFTextBox_Messages.Text ="You are running Windows $OSVersion. This tool is not working with your Version of Windows. You need W10 1709 or higer."
2343 | $WPFTextBox_Messages.Foreground = "Red"
2344 | }
2345 |
2346 |
2347 | #Check if user is Admin
2348 | If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544")) {
2349 | $Script:UserIsAdmin = $true
2350 | }
2351 | else{
2352 | $Script:UserIsAdmin = $false
2353 | }
2354 |
2355 |
2356 | #Checkthe script is executed within ISE
2357 | If(($host.name).Contains("ISE")){
2358 | $ISEMode=$true
2359 | }
2360 | else{
2361 | $ISEMode=$false
2362 | }
2363 |
2364 |
2365 | #Do the Icon Stuff
2366 | If($RunMode -eq "Script"){
2367 |
2368 | # here's the base64 string of the image
2369 | $base64 = "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAdrElEQVR42u17B3gc5bX2O7OzvfemVe+S5d6NO9gGGQcIAdOSm/ATCCXAnwQCfxJCAjgFyL3khtw0UxyIgzHgChiMsS0JC1uWrGZJlrRalVUvu6vd1bb5z6wsYRNuLrnXjvP8f+Z5RrOzO7P7nfec8573zPeJwf/nG3OpB3Cpt38CcKkHcKm3fwLw9/iR2XPm2RiWUet0us6D7x0IX2qj/24ArFi1RtHd1flcTl7+TUqlSuL3jQV8vrHesdFRt0ql6giHw+0ajbojEU90pLhcHRKpdGDbSy9O/D8DQGpa+ivXfPGGzRtLr4RYLOH9fn/yBxmGQTQagT8wzoyOjGBoaAgjI0OJ4eHh8eGhob6xsbEu+rwnFot1qJQqt1gs7nA4HG4CyKvVavw//9nP+H94ACjsHQaT2f2zn/6EizES5kxbOwa7WhBqeh/ReJzn5Wawags4pQESmRIKhYI36A0wGPQMGQlOJEIkGmXGA+ME0CD6+vr4/v6+aK+3d7DH2+Ohgbv9gYBHxLJupVLZazAYPAajsVMmlY488cQT0UsOQGFR8XWr1q7b8fAjj/LjEwnG31mHD39yHbafGMFgkEeKwwxH/kzoWT/U8EOSCCdHE+JlfIhRMiKllVcaU2CwpmLdhlKcOdMKrU4Lg04PShuQ0RCJWCYej4NSCl5vL7q6OhMdHR1jbre7e2BgwM2yrMfn87nVanUbAVS+detW798NgLSMzKcfeviRB7LyisCIxMzgvsfxx8pBdA4EEGFlyL32IYw0VSAwEUcgEkdYYQMvUUAZHYARQ7CIRmGV+GCVjqOksBgqmQitDR9jLCJGICbl45yWosfCi5UmRqUxMeuuWIseAsFo0NNugIoAkkqlkEjEGBwcxOuvvx557rnnDuQXFDyyZ/fuUxcdALvTVfH8r3+9sKW9CyqVkmne/Qz8xjnCa3i4TIz0tEGjVkOhMUDvyoPCkg5fOAZ/MATfeBi+YBjxRIJ2Hs1uD7Jjp3CD7RQWpcbI8yKwHO105FlKFUYB87It6Hd/hKaqvZjgFWClRoiVVlgcWbj8io0Ehgxt7W48++yzoYMHD97a2FD/+kUDYPbc+apgKNz71FNPyfcfOMha5TEceecNeIJyMCyH+JybwAw0I8ZKEWPE5HkVlBryHIW4mgBSKhQU5hosnFkImVKFE00d2Lb1N4gPe3D3oiC+UDQBqYxLAiDsEn0WmJy7IR7Yg+jgscn3kwCxFH0iqJwrYS26HcFgEK++thM7/vynASLa9Iqyo8GLAkBObv5Cm9P10a233Jx4Y9ceNl/Wi/aBEPoTesRECiTW/xCJ8WEk/APgfV5EJLpkWsQi5PXoRPIYDY0jHh5HYUE+7EYtdv7iIaydmQanS481tjPITVVBTOEtGClxrMSEcR3k3t8hFvIizrOQy8XTIIgUTqQufgqjo2P46bP/hvbWFjTW1xfUVFedvigAUPm7u3TTtb+kWp84WXOKXSJvxJAvhEp/KsQyBcLLv43EmcMUygxFhAjirGVgTZnTxsdpjwT9ydcisRRjvR0Y2PUE7rrtBqgVQDQcons5LLacRIpFBjblC4ipZ8JX+yw6ogvg6RlDY/X7uH6tEbMLDZAZZ8JS/E1Un6rFlp//Ah53W3w84E+pra7qvSgAOFJc2x559Hs3fXD4KCjUmGu0x6HjxvGH9nRo1nwHnDkTH1Q3g4sHKVdV4ORqSJUayBQqKokKiClfBQOFXCfRAP9gDwbKX4NWweI2yyHMzyZyk056X6WUIGy/je5TofnkXkQ1S0AVAI2NjRgb9uLOL0hQsuQmaFM3Yedbe/DSH19FbfUJj0ajTT918jh/wQGYOXse09ff37Jly5bMba9uZ8RMDLeZKiDmgB3SryBl5dfRHJThnV3bUarvRuWh3ZBnzEaQ02MEBkQpHTjSBVKFEkZnBkVFBNGJMNIlA7ic34XZ5mG4bKrp/Gc4KQZNd8Ao7sbhigZAkYGqqiokiEAnAr34+nVqzFr5bcgNM/GLXz6Pw0fL8dHRQ7sH+/uuFsZ7wQEoLC5xJsB6Hnzgfmb7jp2MXTKGLxhrEUiI8ZLrV1gwbwHeONGGtsr3MJNzw9W3G9cvNcKikyKSYDAyIcJARA5vWIHemAH+mAS54k7MTYnAYSbBJOR20vDJ/E5IbfAqrocNlfjzwWFKGSWOHTtG1UYFLYH20P/KhnXmYwSqEQ8+9Cg8nk58XHHksaGB/h9eFAAcTtd1M+fO37FwwYLE4aNl7Fx1FxbpOnE8koeWuT+D0paOXfv2EQmOIqd/D0qtLVhaoEWCBh6TWaGM90yXuRYsgyt7FjTdvzuP1dlzymBQWox+bimUY7vx1jEpent70dbWRiQox2UlCdxxyxzIMh7BRCSGO+99AIL0bm6s3dTn7dl1UQCw2uxP3XjzbQ8NDA7x3t4+ttRyGpnKMWzjb4Rpye2o80lQfeRtQSdgXvUDKC2REMvLUMsvAafPhitaARPbQ4ZyOMlfjaI0BdSDb0waftboZAQQGMJ5P7sEIUkBop5t2FulQU1NjSCbYTUb8N07UoWSDM72VXR4PPjBj7fA2+WJjw4PZ3rcrZ6LA4Dd+d7d935z1YdHjjKJRJz5qquamB74lf5nyCtZiEM1LUA8Bie6saDpB1g/zwgRx6F8YhWJGglma5tg4gYQ5JWoF23CHKsXikDltNEiTvRJFNB5c2Q1VGo9/J49eKNCiuMfH6PGahRzi8144ltzoLYtBdRrUVVdg1//biua6mv7ObHYfqapIXHBAcjNL5SGJyK9d951l/adAwcZjTiCr6bXYl9gNrpnPATOlI5DB/Yhs2g2sluexzLREZRkqBFiNOhTLkWYeKKYOUjylUVn0Ixh3VWYpToGadSDUFyMupEMzLJ6oFJMAkAJj+OjVyDTEgLjq4Bt1mbs2vEgKo6GsHBuHm7clIdxyVriiSLse/sA9r79Dqoqyw8TAa6YGvMFBSA9M3u2wWQ9sWHDehwtr2Dy1CNYbOrBD6MPYv78pTgTEKH2vddgIGBuZLdjbYkGGpUYA9HZSLxZA+mNa2BTVCSNOzmUAmnqepSwOyFiJtAbcaK2z4hlKU3Qqblk+Id4DaqHl2Cmk3gjTn1A3gK8+Id7EAlk4frSOTCZlOjnr4Vc5cIvnnsejU1NqDpW/ovhoYEHLgoAFpv9G5etXPvv1H3xpLuZNbZuDPAqvG+9HzkFM3GChEh3QyVyJqpxZ04L5uZqkuHsfzeGgChGkjULpnmj4MQivNeZi/S8+Sjgd5KxLLqYpRiLWZEl2gutahIAb9CBM/4ZWJJWh65hILNkFUXYdxEPmlC6tpgqhQwdoetg0JvwwHcewcjwMBrrqr9MFeCliwKA0WT5IxHg5pbWVoRCYebL2a2wKCZQ6UvBGS0Nri2KviAHSXwcP07bgwV5WoQCCcSOxMAWipAYlsK6WpHM9bdaSzCvyIFM9sPk+aDmS4glJEiJ7aDInyTE+v4MjCRysDKjAoerx3CgSo4UuxZ5jm5sWOGklDKiw78GHAH46A9+BDKc7+/1lni7PXUXBQCbM/X09V+6Maf61ClGwiaY+4qbIRazSbISBiyw4UCIQ/+EDCZJEKlWOeK1IQSMOoiiJH9ZFVJncvBTy/tO11ysLuZhF9VRdydFv+oGxMc7kK8+Pk2CB1uyodVZsSj9BPwhoG54LbTRNzGjwJxUiv0Bolr/7OQTp1//9g9wt7b4SCBZOtpaph+7XTAA0rNyTGKxtHv12su5+oYG1qkM48sFnumydW7p+uRchOH9QSjXaeCvozGlaJCaxeJ0rxQt0cW4PLeLJLQXQ3wmesakkCvUKDLW070ceEaEnVU5KMmRothxBk2dLIKSxUhXHYbNpkmC3tKbjeFQBuV+M97avRd11cc/IgJcfO64LxgAVrtjQ1Zu4b7MzEy+3d3BLLCOYl360Nn6zZ4PxNnzoD+BgSoGuRsUcB8KQTFLDaedw3uNUsSNK+j+4/DV96DvPQn010mBVilc66XUN0jgC0uxpzodq2bHkGr0orYrHcFwDAsL+qFQSJLff6y5gBRgGvbsewfHq06i7uTHvyEC/PpFAUBvMP1o5dp1j4bDExjz+Zgv5vahyBz6i9586lxE5x0VEXDpaooeyvH9Q5CuNMNolGBbuQIpuYuwWHEIilc96F+YBvsSFYmJBoxelQdHiRpNXgWOu13YuMiHBE8V0XIL/rjtGdxzoxoKAohQxrvHi+BKzcJPfv4sqD9BY+3J+0aHh567KACYLPb3r9hw1apeUmGRiQnmm3MpfBX8J4Zzn4iXqfCv2RFB8fUK8hiHoV0j0G6yQCrh8K/vabF8QQ4cb7wGiSsDTmpoBOILvFSLcE4e7Gs0OFSrQA+11zet7EH7kA0nm+UI+07iX64zQiaTwE8RcuDjTGSmp+PRx36MsdFhQQUuG+jzll1wAFJSM6RklHfN5et0kUiEYSMjuDWr7rx8Zz+V/73tEXTXibD4BmUSjLY/DSDzFjsCERH+UGbFEicH5/46WO4yw5CiTN7jO9CG4IACrjvSse2AFCqdC9cv70ZffD3eL2tFlrmFgFMkr233KlFxygqT0YBn/u2XgvHkl7C12+MeveAAmK32AovdWb9s6TJGr9dBH6Ear6g+L/cFI0XnnNfs8VGTYkDxfA7BEI8PnhvFxu/Z0NjN4IgnE0vH22AYCyPnDut01Iwd6oCPCljqt/Lw7J/FWDjbhmVF/fDJvoZ3Dx7GqpIW8rh6Mv9rlWh068CyLLa9sh0tjbWN/b09hZ8e+wUBQKPTL83MKTianp6BtatXQDdWDkf0xDk5P2mA6BwSLHt5DM4VBuTmSdDjCaNh/wQ2PGjF/hNx9ESLUOovh5pRwvhF8zRofVtPIq5Nh2SDFb/dLca1lxuojQ5CarsdL778H7j/Fg5KpTQZaW++L0cwYk0+Li8/VonjH5W9QgDcfFEAKCgsNoYmou0OV5p61swZmJ2uQOr4XsjEOK91nfKkcB7nmckHmlIODWVEZBIZ5qzQ4rfvxiE3FmBjogxsnxyWW+1JIIP+KDyP1UF3az4GjGq887EKX7tGjihjgj8xhwhuN265Wk4qkkuW219t45CRUYiPKj9Gd3cPDry991v9fd6nLwoAy1estFdWHnty9ryFX9EbzfD5fBDTIErXLoKCHQc70Y94qB862QSsOgZaJUsDZc/hBi55pD94fHsC80sycOWMHoRGEzC4lEnAOj7oxsixBGb9n0zsKQuhuceC/30rg4HRKCprY5hVpEJx3uTDkkCIxb9ujeOypUtw6HAZPB43Pio7csWZluYDFxSAq64qXej3+x/bvHnz2oLCQk54T5ixSfA8urp64OnsRGB8HGJOjBi1wIcOHxUkMuRUpSxaBnYDC4dBBIdJDIt+UjE+t4fFtaspt/PHziNOIWKikQTUejl+/uIg5OpU3H8zP11i2XPa5GZ3HC9ThSm9ch2OnziJY8cq4h53e1pFeVn3BQFgxYoV8xUKxfe/fuedG0xmC3uqoYmpOnECDfV16OxwQ6vVISsrCxmZmbDb7bzZbKL6bqQSJ0FvXz+6e7wYHR1lBHACgXGMjI5ibIzSIBEn6SxGul2KbAcLp5W0v01KRyl0WgnEEuoXwOKbT3Vj1dIsbL6KmSbYc8Ha9e44yo/HcPONX0J942m8/OIL3XKFPPWtN3Ym/kcAXHHFFXOJVR+55557NnHUYfx+6wvMRCyB/MIi9PX2oqXpNDra25JfKxJLKMzFkzsnHCXQ6fRISXHCbrPyQqQI01ZiCn+xMBEaiVA1CBIwPmZiYoIiJk7REsLg0DCMBh1mzciDRsmDo5T6oLwbc2cosX65AjaLjISPeNr4prYJPP/CEByOFFxdeiV6COxHv/vwvuPHP77qs2z6XACsWbOmmA4/vPfeezfpdDrR448/jkOHDgnzf5g5ey4WzC8h9ReCl34sFAzh1KlTCJNBIu4sAAIYZ0GYAkRrtGDWsnWwONLw0cFdkI738yoSOxzDI046f4LUXZyGJ1zv9wcwHgwyQgTpdTphBhktrW3JiQ6h2bJblEhNUVHqsWj3RJNzgl//2r8kp+GE6Lr7rru+X1NT/aO/GYBVq1cXx6LRH9x///2blCoV98zTz+DAgXcZnnJcmOMvLV2DJ598FuLxJmLZP8FS8AVqXv6Eh3/sQY93AGryOMsJxkumgZBSQ1OyYiPWbLwRoWgMv3/lNZyqrcVSeQ+4sA+iCJU1iRRihYo0vwoylQYShZIXQAlHokRwoeQUF3ieUSoVvJAyIpZlhMdqSoUc6WmpWL1yORx2O4RI+t73vjdMpFy8ffufvJ8bgFWrVhVFo9FH7rvvvuu1Op14y5YtPHmc4ROJZC3PIM9vujpB5KXF+k0vgolP4HTFy+ge6EaTZxQdXjnMNgdc4Q9QnG1E66gUxwetGFaUoHjxOmLrLJyoqcGrr78FTqlHWn4JnPXbIAqPTQMgESZJFMrkUSYc5crpc2HOgJPJkxOn46EQHwsHMdDTmYw8m9XCrF6+hBexTGL37t01fX19dxsMhkphoqSzs3NqYQX/mQCsW78+LxAIPHLP3fds1un13NNPP40PDr6fnIOf2nJyconYbPjGNRwO76uFIvcqLF59FV559TXK7xTk5+ch1a7D7g/L0TXBoWbMiDFei3SnHUXpTsiYGA5+eCjJGba8uSguSkXx0JvwU60e6RyGbqgXAaUOlCPJCPjPAJg8KpJHq8kIg0KUeOLxH/HkdbalseZAOBS+nSJkgMYurDzhhdLMC6E7abywf/JQ9Kabbsro6ur64R133HGjze7gtm7dyry9fz/iYerm6NrR8WDyahkVumvnkMeMCsgpfNNMUoy5LoM4UEN56gMnkUOvZhGSW/F04GvIcTmRajVCr5IT2TF4Y/97aDldD7lKC9ecVSg0+PAV3XbkOIgMpWK0vDeI8SMDYIZ64Av60SPVYaCgGJKMDLASaoiknw3ASL839vZbryMRj4luu3kz89MtT7xZV1t78znePtfzginTK0iY9es3mLOzs04/88wzhsGhocR9996baGhoEA319TFZWZkYovKkoBJjiZzBNUUsNT5FKOAzoRjsgT4RxjAvRtysRxc/jBHtKBgiqvvbr8WgOB2FaZNez3Ea8efXX8epplboXTmwFSxC0cRBfMn0AXLSNAScGKff7QAXjYInYBOhBML94+C9o1B/5ym8+ebrYAmgzbdtRoSXo6d3FAmWeEXJ8IeP1EVrT1QSxYjZVFcKrt1USqz/0Ov19fVf/RQAwi6E8nmr1JjVq9ekZ2Rlt5WWljIWiwVajTo2PDQU7+lwMxqjSfL22/txsroa6wvtfFbAy6wxGFHZNYaeMS+WsGJs7RzA9XPykE61vz7ahD5i5O+2XwMLdWEpdivyc3Jw4HA5vMRb5uxZ4BMxzO3/D1yV1oX8LH2y7o+Smit7sh3iiRAMCR8sIgKdD6Jm+ZVoIN4RizTU5KRRYyMiLSDB0PBIMiVOtjcnPN0hhkozI5NJYTaZcA0B8PB3vvXa6cbGOz/lecHr439BgqtWrXHYbfaOzOwcbozKjTBdatDrhVqNFKcDJvpStUrJi6N+XuLthvR0E1stEycmWhrwUflJNqFK4AarCZaWVtTkJ1ANBf59uJQkrwpmOTCjsAD1kiJ4RwJQB9woGXoJa7MDKMg0IMjLsL97DsRkLNPagWJ9GBpxjMgwBjlikK26HN1BDi0tA4hHE6QbJDCTk8qq6lDf2inM//H+QCBZlUiXwGIWANiIbz94//bm5ub7zjFe8Lr/M6vAkiXLTEReXRmZOVJPVze6iZxisViyjRRQNZGCs1jMsJrNSfIThIzQY2voxxn6bo1SgsjJE8zA8YOJLcdOsPuO1CUHk5IpPNaegez8GQiySsywSTCnMBt6ZQLRxp+CYRn4Ygoc8S9Bl1+HzjEFRgMTuGO+n/ilAU4LQyKHo5pOHqGxjIzxGBpJ8H/4cxf6fTxjpTG1uzswZfwkAGZKgY24/767X2lra/v2WRv9/5nxSQAWLVyscTidPdm5+cpO0u8CAALrC3V++qLp13zSCynOlJhGoxIJJcfpcCA91TUpdQkw0g3UB3TB7W5Hf/8A/D7hkVUiKWBcLhcQ86OI24u9vZk4NpwJJctRw5RAPMZAzUWwokiPfQdOkkT2ITs7DzabAL6GgOvkX915jNcZs9kQ6YCG001JJ00ZL+wCKJs2Xok7vvbV3/f39//orPeHPiv0p21bsGCR3Ga1efMLi7We7m4imL6/AsDkduttX4nU19VwVVUnWeEz4fmeTquFk1LGRRHionIoEJLwcIRcRIIkIiyUSK71Cw3WxtP0QaayT8U0juuJksUMw5qZaEyJFal+aORyijyZIG6Sc4rjAT9qqL53dHqwbMkilFVU4Exr+3mGn915u80W0yilomef/rlAgEdpH6R9DH9lY+bNW8AR+fXOKJltPBcAAd1zAZjcJyvn5Vesi55pauTcnk6BgCbfp9FOrQIV3tCo1TxxEwkTK6kyKyPwSVpqajJ9hNVfvjEfPzg0yPuGu5LreuQiP29Qhcl4lhUrHBArMxCMG/nyjxsY0iZMQX4utr70MoaoNxAMFlaQiMWTR+E8HovGJZwo/s6+3c8kEokXxGJJdzQaCeC/2JiZM2exKU5Xz7wFi61dXi96BwaSqyvYSaswaQ+bVAzJ16QMcnNzou2tLVyMp0+YSU8J709eO3nfZcuXo+0MsXRnV0IilXJCJJAmgQCKyWQg7Z5CgKQgIy0NVqsFpDzhJfC7unt4Ei7JZkir0TB5udmk5314/Iknk83RlMfPA4DUaV1NVV9Pl0cgvlphaS19X/C/Mn7SnbSRtN21dNmKjQxpdj+JHqHUCD8y6f1PjJqKBKlYFOtobxXZXRnTEcCc/Vw4Ea5Oo7J1puk0Tx1RnEKaY84DdPJaQZfFYtFkG6wm1edw2Ij4zMmosZGWN5qtyabntR07UH70cDIyzw174qMJPsFLGutruvt6ur8jGE9SvYWu+9wLrpMA2Gz29N5e75fp5tkKpSpLo9WnmixWldXmYPVU96kRSubl1MB7uztjno520YIlyxmhNk+DdDZNBAhEdGw+3cC7MrLicrmCmwJGYP9PwJwcAjt5U/K+8EQYfRSJ8xcuxrLLVgjLX/Hu23tRXnbkPABErIh3OmwU8nuafWOjD9P3tVI8NhGY8c9r/DQAU5tcoVTS/VZibQuxeSGVmAUSqSxXpdZkmswWu9OVKnGkpMJ9pinhcbcxt97+jbMRkPT/2TSZfN3d6cbphjp+2cq1cYViCoCzRn/6+rMkO/W6r68XwgPWpQRAJ5Hfu/sFAI4mI2UKgIDPxzfWVe+g8f6e7nHT3kyp+zevIv+r7TB5TpTgeSP9sJ2+PD0ei80igwvoI8p+hp+/+LIbUtMzWAKGyqCZrpdNe/dY2Yd8fW0NydfbEyq1SjT1c0IEMFOvP2X41OtOTwfsDuckAB433tm/DxXlRwRuipHxouB4AC2NdTvJSb+h61vIUe1/q+GfC4DP2jhS3VKpNEZRkkGd1zLywAIinQK1Vu9yOFNSMnPyZJmZ2cyJyopE3amq2GNPPiNRazQ4LwKA8/jiXH4Q/ghPlgTFR7yEjg53MgXKjh5O2MymeEtLC+tubX6BwNhJzqiiY+9/1/j/FgB/ESUKJY2foYIPMxGaKzIxMYtycY7AcfR+G/HEo0UzStgsEjUkuEDpNM0TmD5+wgcCGDXVVaQhDBQBy5OCSgDg6IcfQC6RhCo/KvslXXiIjC8n40f/Z6O/SIulqYqIpFJZgkjVEBwfX0n1eB5FTolGp8tMcaW5cvIKFCS8mKzkswVnUnILyTvFH0ePHEoCsGTZZXC3t+HtfbuxfdsL3aPDQ8LaPg/V+CP0nZ+rzF0SAD5r02i1StIB1lg04qIaPZO8N18mV6QbzeaM3LxCa8msOZzwcFVQjSerjmPBosWUAstRdbwSP/7+dztIU/yKAKoglCp44oILNa5L9m9zKpWaNAyno9Jmj8djmaTvFxDBzVJptJkEls1kMgt9hbexoa6KyHefTCYvCwbHPRd6HP9Q/zdIGkROFcdGpKonfcESu0co13tHR4b7L9Zv/kMBcCm2fwJwqQdwqbf/C3pgOfVSQHzMAAAAAElFTkSuQmCC"
2370 |
2371 | # Create a streaming image by streaming the base64 string to a bitmap streamsource
2372 | $bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
2373 | $bitmap.BeginInit()
2374 | $bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($base64)
2375 | $bitmap.EndInit()
2376 | $bitmap.Freeze()
2377 |
2378 | # This is the icon in the upper left hand corner of the app
2379 | $Form.Icon = $bitmap
2380 |
2381 | # This is the toolbar icon and description
2382 | $Form.TaskbarItemInfo.Overlay = $bitmap
2383 | $Form.TaskbarItemInfo.Description = $Form.Title
2384 | }
2385 |
2386 |
2387 | #endregion
2388 |
2389 | #region ListView_MSIXPackages Sort Function
2390 |
2391 | $ListView_MSIXPackagesSortAction= {
2392 | $col =$_.OriginalSource.Column.Header
2393 | $view = [System.Windows.Data.CollectionViewSource]::GetDefaultView($WPFListView_MSIXPackages.ItemsSource)
2394 | $view.SortDescriptions.Clear()
2395 |
2396 | if ($script:ListInstalledSort -eq 'descending'){
2397 | $desc = New-Object System.ComponentModel.SortDescription($col,'Ascending')
2398 | $script:ListInstalledSort = 'ascending'
2399 | }
2400 | ElseIf ($script:ListInstalledSort -eq 'ascending'){
2401 | $desc = New-Object System.ComponentModel.SortDescription($col,'Descending')
2402 | $script:ListInstalledSort = 'descending'
2403 | }
2404 | Else{
2405 | $desc = New-Object System.ComponentModel.SortDescription($col,'Ascending')
2406 | $script:ListInstalledSort = 'ascending'
2407 | }
2408 | $view.SortDescriptions.Add($desc)
2409 |
2410 | }
2411 | $ListView_MSIXPackagesEvent = [Windows.RoutedEventHandler]$ListView_MSIXPackagesSortAction
2412 | $WPFListView_MSIXPackages.AddHandler([System.Windows.Controls.GridViewColumnHeader]::ClickEvent, $ListView_MSIXPackagesEvent)
2413 | #endregion
2414 |
2415 |
2416 | #region Actions
2417 |
2418 | #Installed Actions
2419 | $WPFButton_GetSoftware.Add_Click({
2420 |
2421 | If($WPFListView_MSIXPackages.ItemsSource){
2422 | $WPFListView_MSIXPackages.ItemsSource.Clear()
2423 | $WPFListView_MSIXPackages.Items.Refresh()
2424 | }
2425 | Get-InstalledMSIX
2426 | Use-Filter
2427 | $WPFTextBox_Messages.Text = "Got the list of Appx/MSIX installed software"
2428 | $WPFTextBox_Messages.Foreground = "Black"
2429 |
2430 | })
2431 |
2432 | $WPFButton_Filter.Add_Click({
2433 | Use-Filter
2434 | })
2435 |
2436 | $WPFButton_Open_Manifest.Add_Click({
2437 | Open-Manifest
2438 | })
2439 |
2440 | $WPFButton_OpenInstallLocation.Add_Click({
2441 | Open-InstallLocation
2442 | })
2443 |
2444 | $WPFButton_OpenUserData.Add_Click({
2445 | Open-UserData
2446 | })
2447 |
2448 | $WPFButton_Uninstall.Add_Click({
2449 | uninstall-App
2450 | })
2451 |
2452 | $WPFButton_Start.Add_Click({
2453 | Start-App
2454 | })
2455 |
2456 | $WPFButton_OpenRegedit.Add_Click({
2457 | Open-Tool -tool "regedit.exe"
2458 | })
2459 |
2460 | $WPFButton_OpenNotepad.Add_Click({
2461 | Open-Tool -tool "notepad.exe"
2462 | })
2463 |
2464 | $WPFButton_OpenCMD.Add_Click({
2465 | Open-Tool -tool "cmd.exe"
2466 | })
2467 |
2468 | #Edit Manifest Actions
2469 |
2470 | $WPFButton_EditManifest_SingelFile_Browse.Add_Click({
2471 |
2472 | $SelectedFile = Select-File -FileType "msix"
2473 | If($SelectedFile){
2474 | $WPFTextBox_EditManifest_SingelFile_SelectedMSIX.Text = $SelectedFile
2475 | }
2476 | })
2477 |
2478 | $WPFButton_EditManifest_SelectFolder.Add_Click({
2479 | $SelectedFolder = $null
2480 | $SelectedFolder = Select-Folder
2481 |
2482 | If($SelectedFolder){
2483 | $WPFTextBox_Messages.Text ="The Folder $SelectedFolder was selected"
2484 | $WPFTextBox_EditManifest_SingelFile_SelectedMSIX.Text = $SelectedFolder
2485 | $WPFTextBox_Messages.Foreground = "Black"
2486 |
2487 | }
2488 | else{
2489 | $WPFTextBox_Messages.Text ="No Folder was selected"
2490 | $WPFTextBox_Messages.Foreground = "DarkOrange"
2491 |
2492 | }
2493 | })
2494 |
2495 |
2496 | $WPFButton_EditManifest_SingelFile_Edit.Add_Click({
2497 |
2498 | $SelectedPath = $WPFTextBox_EditManifest_SingelFile_SelectedMSIX.Text
2499 | If($SelectedPath){
2500 | Edit-Manifest -Path $SelectedPath
2501 | }
2502 | else{
2503 | $WPFTextBox_Messages.Text = "Nothing selected!"
2504 | $WPFTextBox_Messages.Foreground = "Red"
2505 | }
2506 | })
2507 |
2508 | $WPFButton_EditManifest_SelectCertToImport.Add_Click({
2509 |
2510 | $SelectedFile = Select-File -FileType "pfx"
2511 | If($SelectedFile){
2512 | $WPFTextBox_EditManifest_SelectedCert.Text = $SelectedFile
2513 | }
2514 | })
2515 |
2516 |
2517 |
2518 |
2519 | #Change Signature Actions
2520 |
2521 |
2522 | $WPFButton_ChangeSignature_SingelFile_Browse.Add_Click({
2523 |
2524 | $SelectedFile = Select-File -FileType "msix"
2525 | If($SelectedFile){
2526 | $WPFTextBox_ChangeSignature_SelectedMSIX.Text = $SelectedFile
2527 | }
2528 | })
2529 |
2530 | $WPFButton_ChangeSignature_SelectFolder.Add_Click({
2531 | $SelectedFolder = $null
2532 | $SelectedFolder = Select-Folder
2533 |
2534 | If($SelectedFolder){
2535 | $WPFTextBox_Messages.Text ="The Folder $SelectedFolder was selected"
2536 | $WPFTextBox_ChangeSignature_SelectedMSIX.Text = $SelectedFolder
2537 | $WPFTextBox_Messages.Foreground = "Black"
2538 |
2539 | }
2540 | else{
2541 | $WPFTextBox_Messages.Text ="No Folder was selected"
2542 | $WPFTextBox_Messages.Foreground = "DarkOrange"
2543 |
2544 | }
2545 | })
2546 |
2547 |
2548 | $WPFButton_ChangeSignature.Add_Click({
2549 |
2550 | $SelectedPath = $WPFTextBox_ChangeSignature_SelectedMSIX.Text
2551 | If($SelectedPath){
2552 | Change-signature -Path $SelectedPath
2553 | }
2554 | else{
2555 | $WPFTextBox_Messages.Text = "Nothing selected!"
2556 | $WPFTextBox_Messages.Foreground = "Red"
2557 | }
2558 | })
2559 |
2560 | $WPFButton_ChangeSignature_SelectCertToImport.Add_Click({
2561 |
2562 | $SelectedFile = Select-File -FileType "pfx"
2563 | If($SelectedFile){
2564 | $WPFTextBox_ChangeSignature_SelectedCert.Text = $SelectedFile
2565 | }
2566 | })
2567 |
2568 |
2569 |
2570 | #Cert Actions
2571 |
2572 | #Open Browse CertExportFolder Button
2573 | $WPFButton_SelectCertStoreFolder.Add_Click({
2574 | $SelectedFolder = $null
2575 | $SelectedFolder = Select-Folder
2576 |
2577 | If($SelectedFolder){
2578 | $WPFTextBox_Messages.Text ="The Folder $SelectedFolder was selected"
2579 | $WPFTextBox_NewCertFolderName.Text = $SelectedFolder
2580 | $WPFTextBox_Messages.Foreground = "Black"
2581 |
2582 | }
2583 | else{
2584 | $WPFTextBox_Messages.Text ="No Folder was selected"
2585 | $WPFTextBox_Messages.Foreground = "DarkOrange"
2586 |
2587 | }
2588 | })
2589 |
2590 | $WPFButton_CreatCert.Add_Click({
2591 | Creat-SelfSignedCert
2592 | })
2593 |
2594 | $WPFButton_SelectCertToImport.Add_Click({
2595 | Select-Cert
2596 | })
2597 |
2598 |
2599 | $WPFButton_InstallCert.Add_Click({
2600 | Import-CertToTrustedPeople
2601 | })
2602 |
2603 |
2604 | $WPFButton_SelectCertToImportFromMSIX.Add_Click({
2605 |
2606 | $WPFTextBox_SelectedCertFromMSIX.Text = $null
2607 |
2608 |
2609 | $SelectedMSIX = Select-MSIX
2610 |
2611 | $WPFTextBox_SelectedCertFromMSIX.Text = $SelectedMSIX
2612 |
2613 |
2614 | })
2615 |
2616 | $WPFButton_InstallCertFromMSIX.Add_Click({
2617 | Import-CertToTrustedPeopleFromMSIX
2618 | })
2619 |
2620 |
2621 | #Test Actions
2622 |
2623 | $WPFButton_TestSelectInstallMSIXFile.Add_Click({
2624 |
2625 |
2626 | $WPFTextBox_TestSelectedInstallMSIX.Text = $null
2627 |
2628 | $SelectedMSIX = Select-MSIX
2629 |
2630 | $WPFTextBox_TestSelectedInstallMSIX.Text = $SelectedMSIX
2631 |
2632 | })
2633 |
2634 |
2635 | $WPFButton_TestOnlyInstall.Add_Click({
2636 |
2637 | $SelectedPath = $WPFTextBox_TestSelectedInstallMSIX.Text
2638 | If($SelectedPath){
2639 | Install-MSIX -Path $SelectedPath
2640 | }
2641 | else{
2642 | $WPFTextBox_Messages.Text = "Nothing selected!"
2643 | $WPFTextBox_Messages.Foreground = "Red"
2644 | }
2645 | })
2646 |
2647 |
2648 | $WPFButton_TestSelectSingleMSIXFile.Add_Click({
2649 |
2650 | $WPFTextBox_TestSelectedSingleMSIX.Text = $null
2651 |
2652 | $SelectedMSIX = Select-MSIX
2653 |
2654 | $WPFTextBox_TestSelectedSingleMSIX.Text = $SelectedMSIX
2655 |
2656 | })
2657 |
2658 | $WPFButton_TestSingleMSIX.Add_Click({
2659 |
2660 |
2661 | $SelectedPath = $WPFTextBox_TestSelectedSingleMSIX.Text
2662 | If($SelectedPath){
2663 | Test-MSIX -Path $SelectedPath
2664 | }
2665 | else{
2666 | $WPFTextBox_Messages.Text = "Nothing selected!"
2667 | $WPFTextBox_Messages.Foreground = "Red"
2668 | }
2669 | })
2670 |
2671 | $WPFButton_TestSelectMultipleFolder.Add_Click({
2672 | $SelectedFolder = $null
2673 | $SelectedFolder = Select-Folder
2674 |
2675 | If($SelectedFolder){
2676 | $WPFTextBox_Messages.Text ="The Folder $SelectedFolder was selected"
2677 | $WPFTextBox_TestSelectedMultipleMSIXFolder.Text = $SelectedFolder
2678 | $WPFTextBox_Messages.Foreground = "Black"
2679 |
2680 | }
2681 | else{
2682 | $WPFTextBox_Messages.Text ="No Folder was selected"
2683 | $WPFTextBox_Messages.Foreground = "DarkOrange"
2684 |
2685 | }
2686 | })
2687 |
2688 | $WPFButton_TestMultipleMSIX.Add_Click({
2689 |
2690 | $SelectedPath = $WPFTextBox_TestSelectedMultipleMSIXFolder.Text
2691 | If($SelectedPath){
2692 | Test-MSIX -Path $SelectedPath
2693 | }
2694 | else{
2695 | $WPFTextBox_Messages.Text = "Nothing selected!"
2696 | $WPFTextBox_Messages.Foreground = "Red"
2697 | }
2698 | })
2699 |
2700 |
2701 |
2702 | # Packaging Tool Driver
2703 | $WPFButton_PackagingToolDriverCheckStatus.Add_Click({
2704 | Get-PackagingToolDriverStatus
2705 | })
2706 |
2707 | $WPFButton_PackagingToolDriverInstall.Add_Click({
2708 | $WPFTextBox_Messages.Text = ("Installing will take some time. Please be patient.")
2709 | $WPFTextBox_Messages.Foreground = "Black"
2710 | Install-PackagingToolDriver
2711 | })
2712 |
2713 | $WPFButton_PackagingToolDriverUninstall.Add_Click({
2714 | Uninstall-PackagingToolDriver
2715 | })
2716 |
2717 | $WPFButton_StopServices.Add_Click({
2718 | Stop-Services
2719 | })
2720 | $WPFButton_DisableStoreUpdates.Add_Click({
2721 |
2722 | Disable-AutomaticStoreAppUpdates
2723 | })
2724 |
2725 | $WPFButton_Change_SidelaodingStatus.add_click({
2726 |
2727 | $CurrentSideloadingStaus = Check-SideloadingStaus
2728 |
2729 | If($CurrentSideloadingStaus.Contains("Enabled")){
2730 | Disable-Sideloading
2731 | }
2732 | else{
2733 | Enable-Sideloading
2734 | }
2735 |
2736 | $CurrentSideloadingStaus = Check-SideloadingStaus
2737 |
2738 | $WPFTexBlock_CurrentSideloading_Status.Text = $CurrentSideloadingStaus
2739 |
2740 | If($CurrentSideloadingStaus.Contains("Enabled")){
2741 | $WPFTexBlock_CurrentSideloading_Status.Foreground = "#FF0A7211" #Green
2742 | $WPFButton_Change_SidelaodingStatus.Content = "Disable*"
2743 | }else{
2744 | $WPFTexBlock_CurrentSideloading_Status.Foreground = "#FFFF0600" #Red
2745 | $WPFButton_Change_SidelaodingStatus.Content = "Enable*"
2746 | }
2747 |
2748 |
2749 | })
2750 |
2751 |
2752 | $WPFButton_EnableDevMode.add_click({
2753 |
2754 | Enable-DeveloperMode
2755 |
2756 | $CurrentSideloadingStaus = Check-SideloadingStaus
2757 |
2758 | $WPFTexBlock_CurrentSideloading_Status.Text = $CurrentSideloadingStaus
2759 |
2760 | If($CurrentSideloadingStaus.Contains("Enabled")){
2761 | $WPFTexBlock_CurrentSideloading_Status.Foreground = "#FF0A7211" #Green
2762 | $WPFButton_Change_SidelaodingStatus.Content = "Disable*"
2763 | }else{
2764 | $WPFTexBlock_CurrentSideloading_Status.Foreground = "#FFFF0600" #Red
2765 | $WPFButton_Change_SidelaodingStatus.Content = "Enable*"
2766 | }
2767 |
2768 |
2769 | })
2770 |
2771 | #AppAttach Actions
2772 |
2773 |
2774 | $WPFButton_AppAttachConvertToVHD_SingelFile_Browse.Add_Click({
2775 |
2776 | $SelectedFile = Select-File -FileType "msix"
2777 | If($SelectedFile){
2778 | $WPFTextBox_AppAttachConvertToVHD_SingelFile_SelectedMSIX.Text = $SelectedFile
2779 | }
2780 | })
2781 |
2782 | $WPFButton_AppAttachConvertToVHD_SelectFolder.Add_Click({
2783 | $SelectedFolder = $null
2784 | $SelectedFolder = Select-Folder
2785 |
2786 | If($SelectedFolder){
2787 | $WPFTextBox_Messages.Text ="The Folder $SelectedFolder was selected"
2788 | $WPFTextBox_AppAttachConvertToVHD_SingelFile_SelectedMSIX.Text = $SelectedFolder
2789 | $WPFTextBox_Messages.Foreground = "Black"
2790 |
2791 | }
2792 | else{
2793 | $WPFTextBox_Messages.Text ="No Folder was selected"
2794 | $WPFTextBox_Messages.Foreground = "DarkOrange"
2795 |
2796 | }
2797 | })
2798 |
2799 |
2800 | $WPFButton_AppAttachConvertToVHD_Convert.Add_Click({
2801 |
2802 | $SelectedPath = $WPFTextBox_AppAttachConvertToVHD_SingelFile_SelectedMSIX.Text
2803 | If($SelectedPath){
2804 | ConvertTo-VHD -Path $SelectedPath
2805 | }
2806 | else{
2807 | $WPFTextBox_Messages.Text = "Nothing selected!"
2808 | $WPFTextBox_Messages.Foreground = "Red"
2809 | }
2810 | })
2811 |
2812 |
2813 | #Troubleshoting Actions
2814 |
2815 | $WPFButton_OpenEventLogs.Add_Click({
2816 |
2817 | Open-Eventlogs
2818 | })
2819 |
2820 |
2821 |
2822 | #endregion
2823 |
2824 |
2825 | #===========================================================================
2826 | # Shows the form
2827 | #===========================================================================
2828 |
2829 | If($ISEMode){
2830 |
2831 | $Form.ShowDialog() | out-null
2832 | }
2833 | else{
2834 |
2835 | $Form.Add_Closing({[System.Windows.Forms.Application]::Exit(); Stop-Process $pid})
2836 |
2837 | # Make PowerShell Disappear
2838 | $windowcode = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);'
2839 | $asyncwindow = Add-Type -MemberDefinition $windowcode -name Win32ShowWindowAsync -namespace Win32Functions -PassThru
2840 | $null = $asyncwindow::ShowWindowAsync((Get-Process -PID $pid).MainWindowHandle, 0)
2841 |
2842 |
2843 | # Allow input to window for TextBoxes, etc
2844 | [System.Windows.Forms.Integration.ElementHost]::EnableModelessKeyboardInterop($Form)
2845 |
2846 | $Form.Show() | out-null
2847 |
2848 | # This makes it pop up
2849 | $Form.Activate() | out-null
2850 |
2851 | # Create an application context for it to all run within.
2852 | # This helps with responsiveness and threading.
2853 | $appContext = New-Object System.Windows.Forms.ApplicationContext
2854 | [void][System.Windows.Forms.Application]::Run($appContext)
2855 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MSIX Commander
2 | The MSIX Commander is a tool for the packaging engineer and IT-Support staff, that deal with MSIX Packages.
3 |
4 | If you want to use all the features the tool offers you will need Windows 10 1809 or higher.
5 | Parts of it will also work with Windows 10 1803 and 1709.
6 |
7 | # Install:
8 | you can directly install it from here:
9 | https://msixcommander.azurewebsites.net/MSIX_Commander.AppInstaller
10 |
11 | # Download:
12 |
13 | https://github.com/bergerpascal/MSIX_Commander/releases
14 |
15 | Or from here and use the AppInstaller technology that provides auto update functionality:
16 | http://msixcommander.azurewebsites.net/
17 |
18 | # Tested on:
19 | - Windows 10 x64 1803
20 | - Windows 10 x64 1809
21 | - Windows 10 x64 1903
22 | - Windows 10 x64 1909
23 |
--------------------------------------------------------------------------------
/ReleaseNotes.txt:
--------------------------------------------------------------------------------
1 | V1.0.7.5
2 | New:
3 | - Shows if a Package is an MSIX or an Appx (Added by Timothy Mangan)
4 | - Shows if a Package uses the PSF (Added by Timothy Mangan)
5 | - Made the List of the Installed Packages sortable.
6 | - Added Option to open the MSIX related Event Logs form a selectable Time Period
7 | - MSIX Commander is now also available to install trough an AppInstaller File.
8 | If you install it that way you will get automatic Updates, and never have to worry again that you miss a new version.
9 |
10 | V1.0.7.4
11 | New:
12 | - Button to disable automatic Updates of Windows Store Apps
13 |
14 | V1.0.7.3
15 | New:
16 | - Start Button that lets you start the Applications from a selected MSIX
17 |
18 | Fix:
19 | - Stage Scrip now uses Mount-DiskImage instead of Mount-VHD
20 | - Optimized the download of the msixmgr tool so that it works even when you now longer have IE installed
21 | - Improved the generated Stage Script to attach a vhd. It now waits for the staging to finish bevor it returns the status.
22 | - Fixed a Bug where the Tool failed when there was a " in the path to the pfx.
23 |
24 |
25 | V1.0.7.2
26 | Fix:
27 | - Fixed a problem that the Hyper-V role was needed to create a app attach vhd.
28 | - Fixed a problem where sometimes the size of the vhd was to small
29 |
30 | V1.0.7
31 | New:
32 | - Added the possibility to convert MSIX packages to a vhd for MSIX AppAttach.
33 |
34 | V1.0.6
35 | New:
36 | - If you set a Filter it will now also get used after uninstalling an MSIX and when you click
37 | - You can now install a Certificate directly from an MSIX
38 |
39 | Fix:
40 | - Fixed a problem with loading the MSIX Packages that occurred when only one or no MSIX was installed.
41 |
42 | V1.0.5.4 21:01 26.06.2019
43 |
44 | New:
45 | - Now also available as an MSIX
46 | - Let's you not only enable sideloading but also Developer Mode
47 | - You can now open a CMD, Regedit or notepad inside your MSIX Container, almost like the /appvve: paramter for App-V
48 |
49 |
50 | Fix:
51 | - Error on startup when sideloading has never been activated
52 | - Fixed some writing errors
53 |
54 | V1.0.4 00:07 15.06.2019
55 |
56 | New:
57 | - Showing Dependencies (Modification Packages) of installed MSIX Packages
58 | - Shows if sideloading is activated or not and allows to change the status
59 |
60 | Fix:
61 | - Fixed some writing errors
62 |
63 | V1.0.3 16:38 29.03.2019
64 |
65 | New:
66 | - Open Manifest Button
67 | - Added the Edit Manifest Tab. It lets you change the Min- and Maxversions in a Manifest of one ore multiple MSIX Files automatically.
68 | - Added the Change Signature Tab. If you sing your packages with a self singed testcert and later want to change the signature to a productive cert, you can do that for one ore multiple MSIX Files automatically.
69 | - Added the stop services button to the Packaging Machine tab, it lets you stop and disable some services to get a quieter machine and less trash in your package.
70 |
71 | Fix:
72 | - Set some Value for the Minimum Size for the MSIX Package ListView
73 | - Doubled the size of the Message Textbox to let you see more of the information provided there without making the window larger.
74 | - Changed the Filter to get SignatureKind Developer (New after 1903) and Enterprise
75 |
76 |
77 | V1.0.0 23:19 14.03.2019
78 |
79 | New:
80 | - Show all installed MSIX packages
81 | - Open the install directory and user data directory of those installed MSIX packages
82 | - Uninstall MSIX packages
83 | - Create a self-signed code signing certificate
84 | - Install a self-signed code signing certificate
85 | - Install an MSIX package
86 | - Install an MSIX package just to test it.
87 | - Install multiple MSIX packages to test them.
88 | - Check the status of the MSIX packaging tool driver
89 | - Install the MSIX packaging tool driver from Windows Update
90 | - Uninstall the MSIX packaging tool driver
91 |
92 | Fix:
93 | - First Version, therefore, no fixes yet
--------------------------------------------------------------------------------