diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 3904ef1c55..1e7abbb5b3 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -139,6 +139,7 @@ Bicubic bigbar bigobj binaryformatter +binlog binskim bitmapimage BITMAPINFO @@ -158,6 +159,7 @@ Bokm BOKMAL boolalpha Bools +Boostrapper bootstrapper Bopomofo BOTTOMALIGN @@ -417,6 +419,7 @@ diffing difftime DIIRFLAG dimm +directshow dirs DISABLEASACTIONKEY dispid @@ -456,6 +459,8 @@ dshow dst DSVG DText +dupenv +DUSTIN dutil DVASPECT DVASPECTINFO @@ -493,6 +498,7 @@ editshortcutswindow efgh EFile egistry +ekus elif elseif Emoji @@ -520,6 +526,8 @@ ERRORMESSAGE ERRORTITLE ESettings esize +esrp +estdir etcore etl etw @@ -611,6 +619,8 @@ FZE gabime GAC gacutil +Gamebar +GBarm GBs GCLP gcnew @@ -635,6 +645,8 @@ globals GNumber google GPTR +Grayscale +gtm gui guiddef GUITHREADINFO @@ -723,6 +735,7 @@ htcfreek HTHUMBNAIL Htmdid HTTRANSPARENT +Hvci hwb HWINEVENTHOOK hwnd @@ -1143,6 +1156,8 @@ MIIM millis mimetype mindaro +Minimatch +Minimizeallwindows MINIMIZEBOX miniz minlevel @@ -1221,6 +1236,7 @@ MYICON NAMECHANGE nameof namespace +namings NATIVEFNTCTL NCACTIVATE ncc @@ -1312,6 +1328,8 @@ Noto NOTRACK NOUPDATE NOZORDER +NPH +npm npos NResize ntdll @@ -1425,6 +1443,9 @@ PKBDLLHOOKSTRUCT PKEY plib PLK +ploc +ploca +plocm plugin pluginsmodel PMSIHANDLE @@ -1509,6 +1530,7 @@ pushd PVOID pwa pwcs +pwsh PWSTR pwsz pwtd @@ -1517,6 +1539,7 @@ Qin qit QITAB QITABENT +qps Queryable QUERYENDSESSION QUERYOPEN @@ -1604,6 +1627,7 @@ resw resx retval rexit +rfc rfind RGBQUAD rgbs @@ -1626,6 +1650,7 @@ roslyn royvou Rpc RRF +rrr rshift Rsp rst @@ -1695,6 +1720,8 @@ Setttings SETWORKAREA sfgao SFGAOF +SFP +SHAREIMAGELISTS sharpkeys SHCNE SHCNF @@ -1740,10 +1767,12 @@ sid siex SIGABRT sigdn +SIGNINGSCENARIO signtool SINGLEKEY singlekeyremapcontrol singletones +sipolicy SIZEBOX sizeg Sizename @@ -1767,11 +1796,14 @@ somil Soref SOURCECLIENTAREAONLY SOURCEHEADER +sourcesdirectory +spamming spdisp spdlog spdo -spec'ing +spdth specialfolder +spec'ing spesi splitwstring sprintf @@ -1898,6 +1930,7 @@ tcscpy TCustom tdbuild TDevice +telem tellg Templated templatenamespace @@ -2108,6 +2141,7 @@ webclient webpack webpage website +We'd wekyb Wevtapi wgpocpl @@ -2122,6 +2156,7 @@ wikipedia wil wildcards winapi +winappdriver wincodec Wincodecsdk wincolor @@ -2152,6 +2187,7 @@ Winhook winkey WINL winmd +WINMSAPP winnt winres winrt diff --git a/.pipelines/CIPolicy.xml b/.pipelines/CIPolicy.xml new file mode 100644 index 0000000000..c0e448cba0 --- /dev/null +++ b/.pipelines/CIPolicy.xml @@ -0,0 +1,41 @@ + + + 10.0.0.0 + {2E07F7E4-194C-4D20-B7C9-6F44A6C5A234} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + {A244370E-44C9-4C06-B551-F6016E563076} + \ No newline at end of file diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json new file mode 100644 index 0000000000..8370f8e07a --- /dev/null +++ b/.pipelines/ESRPSigning_core.json @@ -0,0 +1,226 @@ +{ + "Version": "1.0.0", + "UseMinimatch": false, + "SignBatches": [ + { + "MatchedPath": [ + "!(ModernWpf)*.resources.dll", + + "PowerToysSetupCustomActions.dll", + + + "PowerToys.ActionRunner.exe", + "PowerToys.Update.exe", + "PowerToys.BackgroundActivatorDLL.dll", + "Notifications.dll", + "os-detection.dll", + "PowerToys.exe", + "PowerToys.Interop.dll", + "BugReportTool\\BugReportTool.exe", + "WebcamReportTool\\WebcamReportTool.exe", + "Telemetry.dll", + "PowerToys.ManagedTelemetry.dll", + "PowerToys.ManagedCommon.dll", + "PowerToys.Common.UI.dll", + "PowerToys.Settings.UI.Lib.dll", + + "modules\\ColorPicker\\ColorPicker.dll", + "modules\\ColorPicker\\ColorPickerUI.dll", + "modules\\ColorPicker\\ColorPickerUI.exe", + + "modules\\ColorPicker\\PowerToys.ColorPicker.dll", + "modules\\ColorPicker\\PowerToys.ColorPickerUI.dll", + "modules\\ColorPicker\\PowerToys.ColorPickerUI.exe", + + "modules\\Awake\\PowerToys.AwakeModuleInterface.dll", + "modules\\Awake\\PowerToys.Awake.exe", + "modules\\Awake\\PowerToys.Awake.dll", + + "modules\\FancyZones\\fancyzones.dll", + "modules\\FancyZones\\PowerToys.FancyZonesEditor.exe", + "modules\\FancyZones\\PowerToys.FancyZonesEditor.dll", + "modules\\FancyZones\\PowerToys.FancyZonesModuleInterface.dll", + "modules\\FancyZones\\PowerToys.FancyZones.exe", + + "modules\\FileExplorerPreview\\PowerToys.GcodePreviewHandler.dll", + "modules\\FileExplorerPreview\\PowerToys.GcodePreviewHandler.comhost.dll", + "modules\\FileExplorerPreview\\PowerToys.GcodeThumbnailProvider.dll", + "modules\\FileExplorerPreview\\PowerToys.GcodeThumbnailProvider.comhost.dll", + "modules\\FileExplorerPreview\\PowerToys.ManagedTelemetry.dll", + "modules\\FileExplorerPreview\\PowerToys.MarkdownPreviewHandler.dll", + "modules\\FileExplorerPreview\\PowerToys.MarkdownPreviewHandler.comhost.dll", + "modules\\FileExplorerPreview\\PowerToys.PdfPreviewHandler.dll", + "modules\\FileExplorerPreview\\PowerToys.PdfPreviewHandler.comhost.dll", + "modules\\FileExplorerPreview\\PowerToys.PdfThumbnailProvider.dll", + "modules\\FileExplorerPreview\\PowerToys.PdfThumbnailProvider.comhost.dll", + "modules\\FileExplorerPreview\\PowerToys.powerpreview.dll", + "modules\\FileExplorerPreview\\PowerToys.PreviewHandlerCommon.dll", + "modules\\FileExplorerPreview\\PowerToys.SvgPreviewHandler.dll", + "modules\\FileExplorerPreview\\PowerToys.SvgPreviewHandler.comhost.dll", + "modules\\FileExplorerPreview\\PowerToys.SvgThumbnailProvider.dll", + "modules\\FileExplorerPreview\\PowerToys.SvgThumbnailProvider.comhost.dll", + + "modules\\ImageResizer\\PowerToys.ImageResizer.exe", + "modules\\ImageResizer\\PowerToys.ImageResizer.dll", + "modules\\ImageResizer\\PowerToys.ImageResizerExt.dll", + + "modules\\KeyboardManager\\PowerToys.KeyboardManager.dll", + "modules\\KeyboardManager\\KeyboardManagerEditor\\PowerToys.KeyboardManagerEditor.exe", + "modules\\KeyboardManager\\KeyboardManagerEngine\\PowerToys.KeyboardManagerEngine.exe", + + "modules\\launcher\\PowerToys.Launcher.dll", + "modules\\launcher\\PowerToys.PowerLauncher.dll", + "modules\\launcher\\PowerToys.PowerLauncher.exe", + "modules\\launcher\\PowerToys.PowerLauncher.Telemetry.dll", + "modules\\launcher\\Wox.dll", + "modules\\launcher\\Wox.Infrastructure.dll", + "modules\\launcher\\Wox.Plugin.dll", + "modules\\launcher\\Plugins\\Calculator\\Microsoft.PowerToys.Run.Plugin.Calculator.dll", + "modules\\launcher\\Plugins\\Folder\\Microsoft.Plugin.Folder.dll", + "modules\\launcher\\Plugins\\Indexer\\Microsoft.Plugin.Indexer.dll", + "modules\\launcher\\Plugins\\Program\\Microsoft.Plugin.Program.dll", + "modules\\launcher\\Plugins\\Registry\\Microsoft.PowerToys.Run.Plugin.Registry.dll", + "modules\\launcher\\Plugins\\WindowsSettings\\Microsoft.PowerToys.Run.Plugin.WindowsSettings.dll", + "modules\\launcher\\Plugins\\Shell\\Microsoft.Plugin.Shell.dll", + "modules\\launcher\\Plugins\\Uri\\Microsoft.Plugin.Uri.dll", + "modules\\launcher\\Plugins\\WindowWalker\\Microsoft.Plugin.WindowWalker.dll", + "modules\\launcher\\Plugins\\UnitConverter\\Community.PowerToys.Run.Plugin.UnitConverter.dll", + "modules\\launcher\\Plugins\\VSCodeWorkspaces\\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.dll", + "modules\\launcher\\Plugins\\Service\\Microsoft.PowerToys.Run.Plugin.Service.dll", + "modules\\launcher\\Plugins\\System\\Microsoft.PowerToys.Run.Plugin.System.dll", + "modules\\launcher\\Plugins\\WindowsTerminal\\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.dll", + + "modules\\MouseUtils\\PowerToys.FindMyMouse.dll", + "modules\\MouseUtils\\PowerToys.MouseHighlighter.dll", + + "modules\\PowerRename\\PowerToys.PowerRenameExt.dll", + "modules\\PowerRename\\PowerToys.PowerRenameUILib.dll", + "modules\\PowerRename\\PowerToys.PowerRename.exe", + + "modules\\ShortcutGuide\\ShortcutGuide\\PowerToys.ShortcutGuide.exe", + "modules\\ShortcutGuide\\ShortcutGuideModuleInterface\\PowerToys.ShortcutGuideModuleInterface.dll", + + "modules\\VideoConference\\PowerToys.VideoConferenceModule.dll", + "modules\\VideoConference\\PowerToys.VideoConferenceProxyFilter_x86.dll", + "modules\\VideoConference\\PowerToys.VideoConferenceProxyFilter_x64.dll", + + "Settings\\PowerToys.Settings.UI.exe", + "Settings\\PowerToys.Settings.dll", + "Settings\\PowerToys.Settings.exe" + ], + "SigningInfo": { + "Operations": [ + { + "KeyCode": "CP-230012", + "OperationSetCode": "SigntoolSign", + "Parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd \"SHA256\"" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "ToolName": "sign", + "ToolVersion": "1.0" + }, + { + "KeyCode": "CP-230012", + "OperationSetCode": "SigntoolVerify", + "Parameters": [], + "ToolName": "sign", + "ToolVersion": "1.0" + } + ] + } + }, + { + "MatchedPath": [ + "Microsoft.Search.Interop.dll", + "ModernWpf.dll", + "ModernWpf.Controls.dll", + "System.IO.Abstractions.dll", + "Mono.Cecil.dll", + "Mono.Cecil.Mdb.dll", + "Mono.Cecil.Pdb.dll", + "Mono.Cecil.Rocks.dll", + "NLog.dll", + "HtmlAgilityPack.dll", + "Markdig.Signed.dll", + "Mages.Core.dll", + "JetBrains.Annotations.dll", + "ICSharpCode.SharpZipLib.dll", + "NLog.Extensions.Logging.dll", + "concrt140_app.dll", + "msvcp140_1_app.dll", + "msvcp140_2_app.dll", + "msvcp140_app.dll", + "vcamp140_app.dll", + "vccorlib140_app.dll", + "vcomp140_app.dll", + "vcruntime140_1_app.dll", + "vcruntime140_app.dll", + "ColorCode.Core.dll", + "ColorCode.UWP.dll", + "UnitsNet.dll" + ], + "SigningInfo": { + "Operations": [ + { + "KeyCode": "CP-231522", + "OperationSetCode": "SigntoolSign", + "Parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd \"SHA256\"" + }, + { + "parameterName": "Append", + "parameterValue": "/as" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "ToolName": "sign", + "ToolVersion": "1.0" + }, + { + "KeyCode": "CP-231522", + "OperationSetCode": "SigntoolVerify", + "Parameters": [], + "ToolName": "sign", + "ToolVersion": "1.0" + } + ] + } + } + ] +} diff --git a/.pipelines/ESRPSigning_installer.json b/.pipelines/ESRPSigning_installer.json new file mode 100644 index 0000000000..8a2804dd45 --- /dev/null +++ b/.pipelines/ESRPSigning_installer.json @@ -0,0 +1,51 @@ +{ + "Version": "1.0.0", + "UseMinimatch": false, + "SignBatches": [ + { + "MatchedPath": [ + "PowerToysSetup-*.exe", + "PowerToysSetup-*.msi" + ], + "SigningInfo": { + "Operations": [ + { + "KeyCode": "CP-230012", + "OperationSetCode": "SigntoolSign", + "Parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd \"SHA256\"" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "ToolName": "sign", + "ToolVersion": "1.0" + }, + { + "KeyCode": "CP-230012", + "OperationSetCode": "SigntoolVerify", + "Parameters": [], + "ToolName": "sign", + "ToolVersion": "1.0" + } + ] + } + } + ] +} diff --git a/.pipelines/ESRPSigning_vcm.json b/.pipelines/ESRPSigning_vcm.json new file mode 100644 index 0000000000..bcf7b1fb60 --- /dev/null +++ b/.pipelines/ESRPSigning_vcm.json @@ -0,0 +1,50 @@ +{ + "Version": "1.0.0", + "UseMinimatch": false, + "SignBatches": [ + { + "MatchedPath": [ + "modules\\VideoConference\\PowerToys.VideoConferenceProxyFilter_x86.dll" + ], + "SigningInfo": { + "Operations": [ + { + "KeyCode": "CP-230012", + "OperationSetCode": "SigntoolSign", + "Parameters": [ + { + "parameterName": "OpusName", + "parameterValue": "Microsoft" + }, + { + "parameterName": "OpusInfo", + "parameterValue": "http://www.microsoft.com" + }, + { + "parameterName": "FileDigest", + "parameterValue": "/fd \"SHA256\"" + }, + { + "parameterName": "PageHash", + "parameterValue": "/NPH" + }, + { + "parameterName": "TimeStamp", + "parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" + } + ], + "ToolName": "sign", + "ToolVersion": "1.0" + }, + { + "KeyCode": "CP-230012", + "OperationSetCode": "SigntoolVerify", + "Parameters": [], + "ToolName": "sign", + "ToolVersion": "1.0" + } + ] + } + } + ] +} diff --git a/.pipelines/ci/templates/build-powertoys-installer.yml b/.pipelines/ci/templates/build-powertoys-installer.yml new file mode 100644 index 0000000000..3335a5048c --- /dev/null +++ b/.pipelines/ci/templates/build-powertoys-installer.yml @@ -0,0 +1,20 @@ +parameters: + configuration: 'Release' + platform: '' + additionalBuildArguments: '-m' + +jobs: +- job: Build${{ parameters.platform }}${{ parameters.configuration }} + displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }} + variables: + BuildConfiguration: ${{ parameters.configuration }} + BuildPlatform: ${{ parameters.platform }} + pool: + name: WinDevPool-L + timeoutInMinutes: 120 + strategy: + maxParallel: 10 + steps: + - template: build-powertoys-steps.yml + parameters: + additionalBuildArguments: ${{ parameters.additionalBuildArguments }} diff --git a/.pipelines/release-nuget.config b/.pipelines/release-nuget.config new file mode 100644 index 0000000000..88c571211d --- /dev/null +++ b/.pipelines/release-nuget.config @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.pipelines/release.yml b/.pipelines/release.yml new file mode 100644 index 0000000000..e90f57d89a --- /dev/null +++ b/.pipelines/release.yml @@ -0,0 +1,275 @@ +# This build should never run as CI or against a pull request. +trigger: none +pr: none + +pool: + name: WinDevPool-L + demands: ImageOverride -equals WinDevVS16-latest + +parameters: + - name: buildConfigurations + type: object + default: + - Release + - name: buildPlatforms + type: object + default: + - x64 + - name: versionNumber + type: string + default: '0.0.1' + +variables: + IsPipeline: 1 # The installer uses this to detect whether it should pick up localizations + +name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr) +resources: + repositories: + - repository: self + type: git + ref: main +jobs: +- job: Build + strategy: + matrix: + ${{ each config in parameters.buildConfigurations }}: + ${{ each platform in parameters.buildPlatforms }}: + ${{ config }}_${{ platform }}: + BuildConfiguration: ${{ config }} + BuildPlatform: ${{ platform }} + displayName: Build + timeoutInMinutes: 120 # Some of the loc stuff adds quite a bit of time. + cancelTimeoutInMinutes: 1 + steps: + - checkout: self + clean: true + submodules: true + persistCredentials: True + +# Sets versions for all PowerToy created DLLs + - task: PowerShell@1 + displayName: Set Versions.Prop + inputs: + scriptName: .pipelines/versionSetting.ps1 + arguments: -versionNumber '${{ parameters.versionNumber }}' -DevEnvironment '' + + - task: MicrosoftTDBuild.tdbuild-task.tdbuild-task.TouchdownBuildTask@1 + displayName: 'Download Localization Files -- PowerToys 37400' + inputs: + teamId: 37400 + authId: '$(TouchdownApplicationID)' + authKey: '$(TouchdownApplicationKey)' + resourceFilePath: | + **\Resources.resx + **\Resource.resx + **\Resources.resw + appendRelativeDir: true + localizationTarget: false + pseudoSetting: Included + - task: PowerShell@2 + displayName: Move Loc files into correct locations + inputs: + targetType: inline + script: >- + $VerbosePreference = "Continue" + + ./tools/build/move-and-rename-resx.ps1 + + ./tools/build/move-uwp-resw.ps1 + pwsh: true + - task: NuGetAuthenticate@0 + inputs: + nuGetServiceConnections: PowerToysCDPxFeed + - task: NuGetToolInstaller@1 + displayName: Use NuGet 5.10 + inputs: + versionSpec: 5.10 +# this will restore the following nugets: +# - main solution +# - Bug report tool +# - Webcam report tool +# - Installer +# - Bootstrapper Installer + - task: NuGetCommand@2 + displayName: NuGet restore solutions dependencies + inputs: + command: restore + restoreSolution: '**/*.sln' + selectOrConfig: config + nugetConfigPath: .pipelines/release-nuget.config + + - task: CmdLine@2 + displayName: Moving telem files + inputs: + script: | + call nuget.exe restore -configFile .pipelines/release-nuget.config -PackagesDirectory . .pipelines/packages.config || exit /b 1 + move /Y "Microsoft.PowerToys.Telemetry.2.0.0\build\include\TraceLoggingDefines.h" "src\common\Telemetry\TraceLoggingDefines.h" || exit /b 1 + move /Y "Microsoft.PowerToys.Telemetry.2.0.0\build\include\TelemetryBase.cs" "src\common\Telemetry\TelemetryBase.cs" || exit /b 1 + +## ALL BUT INSTALLER BUILDING + - task: VSBuild@1 + displayName: Build PowerToys main project + inputs: + solution: '**\PowerToys.sln' + vsVersion: 16.0 + msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog + platform: $(BuildPlatform) + configuration: $(BuildConfiguration) + clean: true + maximumCpuCount: true + + - task: VSBuild@1 + displayName: Build BugReportTool + inputs: + solution: '**/tools/BugReportTool/BugReportTool.sln' + vsVersion: 16.0 + msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog + platform: $(BuildPlatform) + configuration: $(BuildConfiguration) + clean: true + maximumCpuCount: true + + - task: VSBuild@1 + displayName: Build WebcamReportTool + inputs: + solution: '**/tools/WebcamReportTool/WebcamReportTool.sln' + vsVersion: 16.0 + msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog + platform: $(BuildPlatform) + configuration: $(BuildConfiguration) + clean: true + maximumCpuCount: true + + - task: VSBuild@1 + displayName: Build PowerToysSetupCustomActions + inputs: + solution: '**/installer/PowerToysSetup.sln' + vsVersion: 16.0 + msbuildArgs: /target:PowerToysSetupCustomActions /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog + platform: $(BuildPlatform) + configuration: $(BuildConfiguration) + clean: true + maximumCpuCount: true + + - task: VSBuild@1 + displayName: Publish Settings for Packaging + inputs: + solution: 'src/settings-ui/PowerToys.Settings/PowerToys.Settings.csproj' + vsVersion: 16.0 + msbuildArgs: >- + /target:Publish + /p:Configuration=$(BuildConfiguration);Platform=$(BuildPlatform);AppxBundle=Never + /p:VCRTForwarders-IncludeDebugCRT=false + /p:PowerToysRoot=$(Build.SourcesDirectory) + /p:PublishProfile=InstallationPublishProfile.pubxml + platform: $(BuildPlatform) + configuration: $(BuildConfiguration) + maximumCpuCount: true + + - task: VSBuild@1 + displayName: Publish Launcher for Packaging + inputs: + solution: 'src/modules/launcher/PowerLauncher/PowerLauncher.csproj' + vsVersion: 16.0 + # The arguments should be the same as the ones for Settings; make sure they are. + msbuildArgs: >- + /target:Publish + /p:Configuration=$(BuildConfiguration);Platform=$(BuildPlatform);AppxBundle=Never + /p:VCRTForwarders-IncludeDebugCRT=false + /p:PowerToysRoot=$(Build.SourcesDirectory) + /p:PublishProfile=InstallationPublishProfile.pubxml + platform: $(BuildPlatform) + configuration: $(BuildConfiguration) + maximumCpuCount: true + +#### MAIN SIGNING AREA +# reference https://dev.azure.com/microsoft/Dart/_git/AppDriver?path=/ESRPSigning.json&version=GBarm64-netcore&_a=contents for winappdriver +# https://dev.azure.com/microsoft/Dart/_git/AppDriver?path=/CIPolicy.xml&version=GBarm64-netcore&_a=contents + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + displayName: Sign Core PT + inputs: + ConnectedServiceName: 'Terminal/Console/WinAppDriver Team Code Signing Connection' + FolderPath: '$(BuildPlatform)/$(BuildConfiguration)' # Video conf uses x86 and x64. This path will also work for PowerToysSetupCustomActions which is in a different root dir + signType: batchSigning + batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_core.json' + ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml' + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + displayName: Sign x86 directshow VCM + inputs: + ConnectedServiceName: 'Terminal/Console/WinAppDriver Team Code Signing Connection' + FolderPath: 'x86/$(BuildConfiguration)' # Video conf uses x86 and x64. This path will also work for PowerToysSetupCustomActions which is in a different root dir + signType: batchSigning + batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_vcm.json' + ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml' +#### END SIGNING +## END MAIN + +## INSTALLER START +#### MSI BUILDING AND SIGNING + - task: VSBuild@1 + displayName: Build MSI + inputs: + solution: '**/installer/PowerToysSetup.sln' + vsVersion: 16.0 + msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog + platform: $(BuildPlatform) + configuration: $(BuildConfiguration) + clean: true + maximumCpuCount: true + + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + displayName: Sign MSI + inputs: + ConnectedServiceName: 'Terminal/Console/WinAppDriver Team Code Signing Connection' + FolderPath: 'installer/PowerToysSetup/$(BuildPlatform)\$(BuildConfiguration)' + signType: batchSigning + batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json' + ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml' +#### END MSI + +#### BOOTSTRAP BUILDING AND SIGNING + - task: VSBuild@1 + displayName: Build Bootstrapper + inputs: + solution: '**/installer/PowerToysBootstrapper/PowerToysBootstrapper.sln' + vsVersion: 16.0 + msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog + platform: $(BuildPlatform) + configuration: $(BuildConfiguration) + clean: true + maximumCpuCount: true + + - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1 + displayName: Sign Boostrapper + inputs: + ConnectedServiceName: 'Terminal/Console/WinAppDriver Team Code Signing Connection' + FolderPath: 'installer/PowerToysBootstrapper/$(BuildPlatform)\$(BuildConfiguration)' + signType: batchSigning + batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json' + ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml' +#### END BOOTSTRAP +## END INSTALLER + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: binlog' + condition: failed() + continueOnError: True + inputs: + PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog + ArtifactName: binlog-$(BuildPlatform) + + - task: ComponentGovernanceComponentDetection@0 + displayName: Component Detection + + - task: CopyFiles@2 + inputs: + contents: '**/PowerToysSetup-*.exe' + flattenFolders: True + targetFolder: $(Build.ArtifactStagingDirectory) + + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifact: PowerToySetup' + inputs: + PathtoPublish: $(System.ArtifactsDirectory) + ArtifactName: BuildArtifacts +... diff --git a/.pipelines/restore.cmd b/.pipelines/restore.cmd index 22eb393aaa..41b594c54f 100644 --- a/.pipelines/restore.cmd +++ b/.pipelines/restore.cmd @@ -1,5 +1,8 @@ cd /D "%~dp0" +REM Just in case CDPx (Legacy) doesn't do it +git submodule update --init --recursive + nuget restore ../PowerToys.sln || exit /b 1 powershell.exe -Command "Invoke-WebRequest -OutFile %tmp%\wdksetup.exe https://go.microsoft.com/fwlink/p/?linkid=2085767" diff --git a/.pipelines/versionSetting.ps1 b/.pipelines/versionSetting.ps1 new file mode 100644 index 0000000000..004c6c0a53 --- /dev/null +++ b/.pipelines/versionSetting.ps1 @@ -0,0 +1,42 @@ +[CmdletBinding()] +Param( + [Parameter(Mandatory=$True,Position=1)] + [string]$versionNumber = "0.0.1", + + [Parameter(Mandatory=$True,Position=2)] + [AllowEmptyString()] + [string]$DevEnvironment = "Local" +) + +Write-Host $PSScriptRoot +$versionRegex = "(\d+)\.(\d+)\.(\d+)" + +if($versionNumber -match $versionRegEx) +{ + #$buildDayOfYear = (Get-Date).DayofYear; + #$buildTime = Get-Date -Format HH; + #$buildTime = Get-Date -Format HHmmss; + #$buildYear = Get-Date -Format yy; + #$revision = [string]::Format("{0}{1}{2}", $buildYear, $buildDayOfYear, $buildTime ) + + # max UInt16, 65535 + #$revision = [string]::Format("{0}{1}", $buildDayOfYear, $buildTime ) + #Write-Host "Revision" $revision + + $versionNumber = [int]::Parse($matches[1]).ToString() + "." + [int]::Parse($matches[2]).ToString() + "." + [int]::Parse($matches[3]).ToString() # + "." + $revision + Write-Host "Version Number" $versionNumber +} +else +{ + throw "Build format does not match the expected pattern (buildName_w.x.y.z)" +} + +$verPropWriteFileLocation = $PSScriptRoot + '/../src/Version.props'; +$verPropReadFileLocation = $verPropWriteFileLocation; + +[XML]$verProps = Get-Content $verPropReadFileLocation +$verProps.Project.PropertyGroup.Version = $versionNumber; +$verProps.Project.PropertyGroup.DevEnvironment = $DevEnvironment; + +Write-Host "xml" $verProps.Project.PropertyGroup.Version +$verProps.Save($verPropWriteFileLocation); \ No newline at end of file diff --git a/deps/cxxopts.props b/deps/cxxopts.props index bdd65e5537..25cc72b199 100644 --- a/deps/cxxopts.props +++ b/deps/cxxopts.props @@ -1,5 +1,4 @@ - $(MSBuildThisFileDirectory)cxxopts\include;%(AdditionalIncludeDirectories) diff --git a/deps/expected.props b/deps/expected.props index 0438a61b51..41d58e2bd4 100644 --- a/deps/expected.props +++ b/deps/expected.props @@ -1,5 +1,4 @@ - $(MSBuildThisFileDirectory)expected-lite\include\nonstd\;%(AdditionalIncludeDirectories) diff --git a/deps/restore_git_submodules.props b/deps/restore_git_submodules.props deleted file mode 100644 index bb1ff60ca1..0000000000 --- a/deps/restore_git_submodules.props +++ /dev/null @@ -1,12 +0,0 @@ - - - true - - - - - \ No newline at end of file diff --git a/deps/spdlog.props b/deps/spdlog.props index 85b16b962c..0c755dc5e2 100644 --- a/deps/spdlog.props +++ b/deps/spdlog.props @@ -1,5 +1,4 @@ - $(MSBuildThisFileDirectory)spdlog\include;%(AdditionalIncludeDirectories) diff --git a/installer/PowerToysSetup/PowerToysSetup.wixproj b/installer/PowerToysSetup/PowerToysSetup.wixproj index cab87ecbf9..c056b393bf 100644 --- a/installer/PowerToysSetup/PowerToysSetup.wixproj +++ b/installer/PowerToysSetup/PowerToysSetup.wixproj @@ -3,7 +3,7 @@ - Version=$(Version) + Version=$(Version) Release @@ -73,6 +73,10 @@ + IF NOT DEFINED IsPipeline ( call "$([MSBuild]::GetVsInstallRoot())\Common7\Tools\VsDevCmd.bat" -arch=amd64 -host_arch=amd64 -winsdk=10.0.18362.0 SET PTRoot=..\..\..\.. diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 6a5be47f3d..28d5777612 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -1003,7 +1003,7 @@ - + @@ -1013,16 +1013,48 @@ - - + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + - + @@ -1036,14 +1068,46 @@ - + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + diff --git a/installer/PowerToysSetup/publish.cmd b/installer/PowerToysSetup/publish.cmd index 6f916c9fae..43eab51a3c 100644 --- a/installer/PowerToysSetup/publish.cmd +++ b/installer/PowerToysSetup/publish.cmd @@ -2,62 +2,8 @@ setlocal enableDelayedExpansion IF NOT DEFINED PTRoot (SET PTRoot=..\..) -rem Publish Settings -SET settingsProfileFolderName=!PTRoot!\src\settings-ui\PowerToys.Settings\Properties\PublishProfiles\ -rem Create the publish profile folder if it doesn't exist -IF NOT EXIST !settingsProfileFolderName! (mkdir !settingsProfileFolderName!) -SET settingsProfileFileName=SettingsProfile.pubxml -SET settingsPublishProfile=!settingsProfileFolderName!!settingsProfileFileName! - -rem Create the publish profile pubxml -echo ^ > !settingsPublishProfile! -echo ^<^^!-- >> !settingsPublishProfile! -echo https://go.microsoft.com/fwlink/?LinkID=208121. >> !settingsPublishProfile! -echo --^> >> !settingsPublishProfile! -echo ^ >> !settingsPublishProfile! -echo ^ >> !settingsPublishProfile! -echo ^FileSystem^ >> !settingsPublishProfile! -echo ^Release^ >> !settingsPublishProfile! -echo ^x64^ >> !settingsPublishProfile! -echo ^netcoreapp3.1^ >> !settingsPublishProfile! -echo ^..\..\..\x64\Release\Settings^ >> !settingsPublishProfile! -echo ^win-x64^ >> !settingsPublishProfile! -echo ^false^ >> !settingsPublishProfile! -echo ^False^ >> !settingsPublishProfile! -echo ^False^ >> !settingsPublishProfile! -echo ^ >> !settingsPublishProfile! -echo ^ >> !settingsPublishProfile! +rem In case of Release we should not use Debug CRT in VCRT forwarders +msbuild !PTRoot!\src\settings-ui\PowerToys.Settings\PowerToys.Settings.csproj -t:Publish -p:Configuration="Release" -p:Platform="x64" -p:PowerToysRoot=!PTRoot! -p:AppxBundle=Never -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml rem In case of Release we should not use Debug CRT in VCRT forwarders -msbuild !PTRoot!\src\settings-ui\PowerToys.Settings\PowerToys.Settings.csproj -t:Publish -p:Configuration="Release" -p:Platform="x64" -p:AppxBundle=Never -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=!settingsProfileFileName! - - -rem Publish Launcher -SET launcherProfileFolderName=!PTRoot!\src\modules\launcher\PowerLauncher\Properties\PublishProfiles\ - -rem Create the publish profile folder if it doesn't exist -IF NOT EXIST !launcherProfileFolderName! (mkdir !launcherProfileFolderName!) -SET launcherProfileFileName=LauncherProfile.pubxml -SET launcherPublishProfile=!launcherProfileFolderName!!launcherProfileFileName! - -rem Create the publish profile pubxml -echo ^ > !launcherPublishProfile! -echo ^<^^!-- >> !launcherPublishProfile! -echo https://go.microsoft.com/fwlink/?LinkID=208121. >> !launcherPublishProfile! -echo --^> >> !launcherPublishProfile! -echo ^ >> !launcherPublishProfile! -echo ^ >> !launcherPublishProfile! -echo ^FileSystem^ >> !launcherPublishProfile! -echo ^Release^ >> !launcherPublishProfile! -echo ^x64^ >> !launcherPublishProfile! -echo ^netcoreapp3.1^ >> !launcherPublishProfile! -echo ^..\..\..\..\x64\Release\modules\launcher^ >> !launcherPublishProfile! -echo ^win-x64^ >> !launcherPublishProfile! -echo ^false^ >> !launcherPublishProfile! -echo ^False^ >> !launcherPublishProfile! -echo ^False^ >> !launcherPublishProfile! -echo ^ >> !launcherPublishProfile! -echo ^ >> !launcherPublishProfile! - -rem In case of Release we should not use Debug CRT in VCRT forwarders -msbuild !PTRoot!\src\modules\launcher\PowerLauncher\PowerLauncher.csproj -t:Publish -p:Configuration="Release" -p:Platform="x64" -p:AppxBundle=Never -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=!launcherProfileFileName! +msbuild !PTRoot!\src\modules\launcher\PowerLauncher\PowerLauncher.csproj -t:Publish -p:Configuration="Release" -p:Platform="x64" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml diff --git a/src/modules/keyboardmanager/KeyboardManagerEditor/Resources.resx b/src/modules/keyboardmanager/KeyboardManagerEditor/Resources.resx index 1cceeaeb3a..8090f1c75e 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditor/Resources.resx +++ b/src/modules/keyboardmanager/KeyboardManagerEditor/Resources.resx @@ -188,69 +188,6 @@ For example, if you want to press "Ctrl+C" and get "Alt" only on Microsoft Edge, "Ctrl+C" would be your "Shortcut" column, the key "Alt" would be your "Mapped To" column, and "MSEdge" would be your "Target App" column. If no target app is entered, it will apply globally. The name must be the process name and not the app name. - - Remapping successful - - - Some remappings were not applied - - - Cannot remap a key more than once - Key on a keyboard - - - Cannot remap a key to itself - Key on a keyboard - - - Cannot remap this key as it conflicts with another remapped key - Key on a keyboard - - - Cannot remap a shortcut more than once for the same target app - - - Cannot remap a shortcut to itself - - - Cannot remap this shortcut as it conflicts with another remapped shortcut - - - Cannot remap from/to Win L - Win refers to Windows as in the OS - - - Cannot remap from/to Ctrl Alt Del - - - Failed to save the remappings - - - Shortcut must start with a modifier key - Key on a keyboard - - - Shortcut cannot contain a repeated modifier - - - Shortcut must have atleast 2 keys - Key on a keyboard - - - Shortcut must contain an action key - Key on a keyboard - - - Shortcut cannot have more than one action key - Key on a keyboard - - - Shortcuts can only have up to 2 modifier keys - Key on a keyboard - - - Unexpected error - Type As in type a key diff --git a/src/modules/launcher/PowerLauncher/Properties/PublishProfiles/InstallationPublishProfile.pubxml b/src/modules/launcher/PowerLauncher/Properties/PublishProfiles/InstallationPublishProfile.pubxml new file mode 100644 index 0000000000..f21cb17210 --- /dev/null +++ b/src/modules/launcher/PowerLauncher/Properties/PublishProfiles/InstallationPublishProfile.pubxml @@ -0,0 +1,16 @@ + + + + + FileSystem + netcoreapp3.1 + $(PowerToysRoot)\$(Platform)\$(Configuration)\modules\launcher + win-$(Platform) + false + False + False + false + + diff --git a/src/settings-ui/PowerToys.Settings/Properties/PublishProfiles/InstallationPublishProfile.pubxml b/src/settings-ui/PowerToys.Settings/Properties/PublishProfiles/InstallationPublishProfile.pubxml new file mode 100644 index 0000000000..00dd52bee4 --- /dev/null +++ b/src/settings-ui/PowerToys.Settings/Properties/PublishProfiles/InstallationPublishProfile.pubxml @@ -0,0 +1,16 @@ + + + + + FileSystem + netcoreapp3.1 + $(PowerToysRoot)\$(Platform)\$(Configuration)\Settings + win-$(Platform) + false + False + False + false + + diff --git a/tools/build/convert-resx-to-rc.ps1 b/tools/build/convert-resx-to-rc.ps1 index 748e6c1731..3884c4eafa 100644 --- a/tools/build/convert-resx-to-rc.ps1 +++ b/tools/build/convert-resx-to-rc.ps1 @@ -25,9 +25,6 @@ else $initResourceID = 101 } -# Temporary file created used for resgen -$tempFile = "temporaryResourceFile.txt" - # Flags to check if the first updated has occurred $headerFileUpdated = $false $rcFileUpdated = $false @@ -50,6 +47,7 @@ if (!(Test-Path -Path $generatedFilesFolder)) # Hash table to get the language codes from the code used in the file name $languageHashTable = @{ "en" = @("ENU", "ENGLISH", "ENGLISH_US", "English (United States)"); "zh-Hans" = @("CHS", "CHINESE", "NEUTRAL", "Chinese (Simplified)"); + "zh-CN" = @("CHS", "CHINESE", "NEUTRAL", "Chinese (Simplified)"); "cs" = @("CSY", "CZECH", "NEUTRAL", "Czech"); "hu" = @("HUN", "HUNGARIAN", "NEUTRAL", "Hungarian"); "pl" = @("PLK", "POLISH", "NEUTRAL", "Polish"); @@ -74,6 +72,7 @@ $languageHashTable = @{ "en" = @("ENU", "ENGLISH", "ENGLISH_US", "English (Unite "sv" = @("SVE", "SWEDISH", "NEUTRAL", "Swedish"); "pt-PT" = @("PTG", "PORTUGUESE", "PORTUGUESE", "Portuguese (Portugal)"); "zh-Hant" = @("CHT", "CHINESE", "CHINESE_TRADITIONAL", "Chinese (Traditional)") + "zh-TW" = @("CHT", "CHINESE", "CHINESE_TRADITIONAL", "Chinese (Traditional)") } # Store the content to be written to a buffer @@ -81,14 +80,15 @@ $headerFileContent = "" $rcFileContent = "" # Iterate over all resx files in parent directory -Get-ChildItem $parentDirectory -Filter *.resx | +Get-ChildItem $parentDirectory -Recurse -Filter *.resx | Foreach-Object { - # Use resgen to parse resx to txt. More details at https://docs.microsoft.com/en-us/dotnet/framework/tools/resgen-exe-resource-file-generator#converting-between-resource-file-types + Write-Host "Processing $($_.FullName)" + $xmlDocument = $null try { - resgen $_.FullName $tempFile + $xmlDocument = [xml](Get-Content $_.FullName -ErrorAction:Stop) } catch { - echo "resgen failed to convert resx file" + Write-Host "Failed to load $($_.FullName)" exit 0 } @@ -97,39 +97,50 @@ Foreach-Object { $tokens = $_.Name -split "\." if ($tokens.Count -eq 3) { $lang = $tokens[1] + } else { + $d = $_.Directory.Name + If ($d.Contains('-')) { # Looks like a language directory + $lang = $d + } } + $langData = $languageHashTable[$lang] + if ($null -eq $langData -and $lang.Contains('-')) { + # Modern Localization comes in with language + country tuples; + # we want to detect the language alone if we don't support the language-country + # version. + $lang = ($lang -split "-")[0] + $langData = $languageHashTable[$lang] + } + if ($null -eq $langData) { + Write-Warning "Unknown language $lang" + Return + } $newLinesForRCFile = "" $newLinesForHeaderFile = "" $count = $initResourceID try { - foreach ($line in (Get-Content $tempFile -Encoding unicode)) { - # Each line of the resgen text file is of the form ResourceName=ResourceValue with no spaces. - $content = $line -split "=", 2 - + foreach ($entry in $xmlDocument.root.data) { $culture = [System.Globalization.CultureInfo]::GetCultureInfo('en-US') # Each resource is named as IDS_ResxResourceName, in uppercase. Escape occurrences of double quotes in the string - $lineInRCFormat = "IDS_" + $content[0].ToUpper($culture) + " L`"" + $content[1].Replace("`"", "`"`"") + "`"" + $lineInRCFormat = "IDS_" + $entry.name.ToUpper($culture) + " L`"" + $entry.value.Replace("`"", "`"`"") + "`"" $newLinesForRCFile = $newLinesForRCFile + "`r`n " + $lineInRCFormat # Resource header file needs to be updated only for one language if (!$headerFileUpdated) { - $lineInHeaderFormat = "#define IDS_" + $content[0].ToUpper($culture) + " " + $count.ToString() + $lineInHeaderFormat = "#define IDS_" + $entry.name.ToUpper($culture) + " " + $count.ToString() $newLinesForHeaderFile = $newLinesForHeaderFile + "`r`n" + $lineInHeaderFormat $count++ } } } catch { - echo "Failed to read temporary file." + echo "Failed to read XML document." exit 0 } - # Delete temporary text file used by resgen - Remove-Item $tempFile - # Add string table syntax $newLinesForRCFile = "`r`nSTRINGTABLE`r`nBEGIN" + $newLinesForRCFile + "`r`nEND" diff --git a/tools/build/move-and-rename-resx.ps1 b/tools/build/move-and-rename-resx.ps1 new file mode 100644 index 0000000000..8249cb3c42 --- /dev/null +++ b/tools/build/move-and-rename-resx.ps1 @@ -0,0 +1,29 @@ +[CmdletBinding()] + +# This script finds all C#/.NET resx files and renames them from +# Folder/Language/x.resw to Folder/x.Language.resw, with language +# mapping. This is required because Touchdown localization uses a +# different directory structure. +$Items = Get-ChildItem . -Recurse -Filter *.resx + +# Each of the projects we care about stores its resources +# in a Properties directory. We **DO NOT** want to move +# resource files from other projects (since we use resx files +# in standard Win32 projects as well.) +$Items = $Items | Where-Object { + $_.Directory.Parent.Name -Eq "Properties" +} + +If ($Items.Count -Le 0) { + # Nothing to do. + Write-Verbose "Nothing to do." + Exit 0 +} + +ForEach($Item in $Items) { + $PropertiesRoot = $Item.Directory.Parent + $Language = $Item.Directory.Name + $Destination = Join-Path $PropertiesRoot.FullName ("{0}.{1}{2}" -F ($Item.BaseName, $Language, $Item.Extension)) + Write-Verbose "Renaming $($Item.FullName) to $Destination" + Move-Item $Item.FullName $Destination +} diff --git a/tools/build/move-uwp-resw.ps1 b/tools/build/move-uwp-resw.ps1 new file mode 100644 index 0000000000..ed945a6598 --- /dev/null +++ b/tools/build/move-uwp-resw.ps1 @@ -0,0 +1,18 @@ +[CmdletBinding()] + +# This script finds all UWP resw files that are emitted by Touchdown +# with a bad path (en-us/lang-lang) and moves them to the correct +# location. +$Items = Get-ChildItem . -Recurse -Filter *.resw | + Where-Object FullName -Like "*\en-US\*\*.resw" + +If ($Items.Count -Le 0) { + # Nothing to do. + Write-Verbose "Nothing to do." + Exit 0 +} + +$Items | ForEach-Object { + # Move each resw file's parent folder into its parent's parent's folder. + Move-Item -Verbose $_.Directory.FullName $_.Directory.Parent.Parent.FullName -EA:Ignore +}