├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── ci.yml │ ├── release.yml │ └── virus-scan.yml ├── .gitignore ├── .reposync.yml ├── CONTRIBUTING.md ├── GitReleaseManager.yaml ├── LICENSE.md ├── README.md ├── nuget.config └── src ├── Custom.Build.props ├── Directory.Build.props ├── NServiceBus.PowerShell.CustomActions ├── CustomAction.config ├── CustomAction.cs └── NServiceBus.PowerShell.CustomActions.csproj ├── NServiceBus.PowerShell.Tests ├── MsmqSetupTests.cs ├── NServiceBus.PowerShell.Tests.csproj ├── PerformanceCounterSetupTests.cs └── RegistryHelperTests.cs ├── NServiceBus.PowerShell.sln ├── NServiceBus.PowerShell ├── Cmdlets │ ├── CmdletBase.cs │ ├── CmdletHelperBase.cs │ ├── GetNServiceBusLocalMachineSettings.cs │ ├── InstallDtc.cs │ ├── InstallMsmq.cs │ ├── InstallPerformanceCounters.cs │ ├── InstallPlatformLicense.cs │ ├── InstallationResult.cs │ ├── MachineSettingsResult.cs │ ├── RemoveMSMQWorker.cs │ ├── RemoveNServiceBusLocalMachineSettings.cs │ ├── SetNServiceBusLocalMachineSettings.cs │ ├── UninstallPerformanceCounters.cs │ ├── ValidateDtc.cs │ ├── ValidateMsmq.cs │ └── ValidatePerformanceCounters.cs ├── Dtc │ └── DtcSetup.cs ├── Formats │ ├── NServiceBus.PowerShell.Cmdlets.InstallationResult.format.ps1xml │ └── NServiceBus.PowerShell.Cmdlets.MachineSettingsResult.format.ps1xml ├── Helpers │ ├── Action.cs │ ├── EnvironmentHelper.cs │ ├── ExtensionAttribute.cs │ ├── HeaderInfo.cs │ ├── ProcessUtil.cs │ ├── RegistryHelper.cs │ ├── RegistryView.cs │ ├── StreamExtensions.cs │ └── StringExtensions.cs ├── InternalsVisibleTo.cs ├── Msmq │ └── MsmqSetup.cs ├── NServiceBus.PowerShell.csproj ├── NServiceBus.PowerShell.csproj.DotSettings ├── NServiceBus.PowerShell.dll-help.xml ├── NServiceBus.PowerShell.psd1 └── PerformanceCounters │ └── PerformanceCounterSetup.cs ├── NServiceBus.snk └── Setup ├── NServiceBus.PowerShell.aip ├── Res ├── License.rtf ├── banner.jpg ├── dialog.jpg └── particular.ico ├── Setup.csproj └── commands.aic /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform CRLF normalization 2 | * text=auto eol=crlf 3 | 4 | # Standard to msysgit 5 | *.doc diff=astextplain 6 | *.DOC diff=astextplain 7 | *.docx diff=astextplain 8 | *.DOCX diff=astextplain 9 | *.dot diff=astextplain 10 | *.DOT diff=astextplain 11 | *.pdf diff=astextplain 12 | *.PDF diff=astextplain 13 | *.rtf diff=astextplain 14 | *.RTF diff=astextplain 15 | 16 | *.exe -text -diff 17 | *.jpg -text -diff 18 | *.png -text -diff 19 | *.gif -text -diff 20 | *.dll -text -diff 21 | *.pdb -text -diff 22 | *.pptx -text -diff 23 | *.xap -text -diff 24 | *.ico -text -diff 25 | *.ttf -text -diff 26 | *.otf -text -diff 27 | 28 | *.cs text diff=csharp 29 | *.config text diff=csharp 30 | *.xml text diff=csharp 31 | *.vb text 32 | *.c text 33 | *.cpp text 34 | *.cxx text 35 | *.h text 36 | *.hxx text 37 | *.py text 38 | *.rb text 39 | *.java text 40 | *.html text 41 | *.htm text 42 | *.css text 43 | *.scss text 44 | *.sass text 45 | *.less text 46 | *.js text 47 | *.lisp text 48 | *.clj text 49 | *.sql text 50 | *.php text 51 | *.lua text 52 | *.m text 53 | *.asm text 54 | *.erl text 55 | *.fs text 56 | *.fsx text 57 | *.hs text 58 | *.targets text 59 | *.psm1 text 60 | *.ps1 text 61 | *.md text 62 | *.DotSettings text 63 | *.txt text eol=crlf 64 | *.bat text eol=crlf 65 | 66 | # Custom for Visual Studio 67 | *.suo -text -diff 68 | *.snk -text -diff 69 | *.cub -text -diff 70 | *.wixlib -text -diff 71 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: nuget 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - release-* 7 | pull_request: 8 | workflow_dispatch: 9 | env: 10 | DOTNET_NOLOGO: true 11 | jobs: 12 | build: 13 | name: Windows 14 | runs-on: windows-2019 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v3.2.0 18 | with: 19 | fetch-depth: 0 20 | - name: Setup .NET SDK 21 | uses: actions/setup-dotnet@v3.0.3 22 | with: 23 | dotnet-version: 5.0.x 24 | - name: Add msbuild to PATH 25 | uses: microsoft/setup-msbuild@v1.0.2 26 | - name: Build 27 | run: msbuild src -p:Configuration=Release -restore -m 28 | - name: Upload assets 29 | uses: actions/upload-artifact@v3.1.1 30 | with: 31 | name: Assets 32 | path: src/NServiceBus.PowerShell/bin/Release 33 | retention-days: 7 34 | - name: Run tests 35 | uses: Particular/run-tests-action@v1.4.0 36 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | tags: 5 | - '[0-9]+.[0-9]+.[0-9]+' 6 | - '[0-9]+.[0-9]+.[0-9]+-*' 7 | env: 8 | DOTNET_NOLOGO: true 9 | RELEASE_WORKFLOW: true 10 | jobs: 11 | release: 12 | runs-on: windows-2019 # Code signing requirement https://github.com/NuGet/Home/issues/7939 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v2.3.4 16 | with: 17 | fetch-depth: 0 18 | - name: Parse repo name 19 | run: | 20 | $FullName = "$env:GITHUB_REPOSITORY" 21 | $Org,$RepoName = $FullName.Split('/') 22 | echo "PARTICULAR_REPO_NAME=$RepoName" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append 23 | shell: pwsh 24 | - name: Setup .NET SDK 25 | uses: actions/setup-dotnet@v1.7.2 26 | with: 27 | dotnet-version: 5.0.x 28 | - name: Add msbuild to PATH 29 | uses: microsoft/setup-msbuild@v1.0.2 30 | - name: Setup Advanced Installer 31 | run: | 32 | $version = "18.8.1" 33 | choco install advanced-installer --version=$version 34 | & "C:\Program Files (x86)\Caphyon\Advanced Installer $version\bin\x86\AdvancedInstaller.com" /register ${{ secrets.ADVANCED_INSTALLER_LICENSE_KEY }} 35 | - name: Install NuGetKeyVaultSignTool 36 | run: dotnet tool install --global NuGetKeyVaultSignTool 37 | - name: Prepare AIP file 38 | run: | 39 | $content = Get-Content -Raw -Path src/Setup/NServiceBus.PowerShell.aip 40 | $content = $content -replace "replace-tenant-id", "${{ secrets.AZURE_KEY_VAULT_TENANT_ID }}" -replace "replace-app-id", "${{ secrets.AZURE_KEY_VAULT_CLIENT_ID }}" -replace "replace-cert-name", "${{ secrets.AZURE_KEY_VAULT_CERTIFICATE_NAME }}" 41 | Set-Content src/Setup/NServiceBus.PowerShell.aip $content 42 | - name: Build 43 | env: 44 | AZURE_KEY_VAULT_CLIENT_SECRET: ${{ secrets.AZURE_KEY_VAULT_CLIENT_SECRET }} 45 | run: msbuild src -p:Configuration=Release -restore -m 46 | - name: Publish artifacts 47 | uses: actions/upload-artifact@v2.2.4 48 | with: 49 | name: assets 50 | path: assets/* 51 | retention-days: 1 52 | - name: Install Octopus CLI 53 | uses: OctopusDeploy/install-octopus-cli-action@v1.1.7 54 | with: 55 | version: latest 56 | - name: Create Octopus Package 57 | run: | 58 | # Creating the expected file layout for the Octopus package, including intermediate directories 59 | mkdir -p packaging/content 60 | cp assets\* .\packaging\content 61 | 62 | # Octopus Deploy scripts need an executable file to recreate this metadata 63 | @" 64 | `$Branch = "${{github.ref_name}}" 65 | `$Version = "${{env.MinVerVersion}}" 66 | `$Product = "${{env.PARTICULAR_REPO_NAME}}" 67 | `$Major = "${{env.MinVerMajor}}" 68 | `$Minor = "${{env.MinVerMinor}}" 69 | `$Commit = "${{github.sha}}" 70 | "@ > packaging/Metadata.ps1 71 | 72 | # Create the Octopus package 73 | octo pack --id="${{env.PARTICULAR_REPO_NAME}}.Deploy" --version="${{env.MinVerVersion}}" --format="nupkg" --basePath="packaging" --outFolder="octopus-package" 74 | shell: pwsh 75 | - name: Publish Octopus Package Artifacts 76 | uses: actions/upload-artifact@v2.2.2 77 | with: 78 | name: octopus-package 79 | path: octopus-package/* 80 | retention-days: 1 81 | - name: Push package to Octopus Deploy 82 | uses: OctopusDeploy/push-package-action@v1.1.1 83 | with: 84 | server: https://deploy.particular.net 85 | api_key: ${{ secrets.OCTOPUS_DEPLOY_API_KEY }} 86 | packages: octopus-package/${{env.PARTICULAR_REPO_NAME}}.Deploy.${{env.MinVerVersion}}.nupkg 87 | - name: Create Octopus Deploy release 88 | uses: OctopusDeploy/create-release-action@v1.1.1 89 | with: 90 | server: https://deploy.particular.net 91 | api_key: ${{ secrets.OCTOPUS_DEPLOY_API_KEY }} 92 | project: ${{env.PARTICULAR_REPO_NAME}} 93 | release_number: ${{env.MinVerVersion}} 94 | package_version: ${{env.MinVerVersion}} 95 | package: "GitReleaseManager:0.11.0" -------------------------------------------------------------------------------- /.github/workflows/virus-scan.yml: -------------------------------------------------------------------------------- 1 | name: Virus scan 2 | on: 3 | release: 4 | types: [published] 5 | jobs: 6 | virus-scan: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Scan release for viruses 10 | uses: Particular/virus-scan-action@main 11 | with: 12 | owner: ${{ github.repository_owner }} 13 | repo: ${{ github.event.repository.name }} 14 | tag: ${{ github.event.release.name }} 15 | github-access-token: ${{ secrets.GITHUB_TOKEN }} 16 | slack-token: ${{ secrets.SLACK_TOKEN }} 17 | slack-channel: ${{ secrets.VIRUS_REPORTING_SLACK_CHANNEL }} 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | nugets 2 | deploy 3 | build32 4 | binaries 5 | *.vshost.* 6 | .nu 7 | _UpgradeReport.* 8 | *.cache 9 | *~ 10 | *.swp 11 | results 12 | CommonAssemblyInfo.cs 13 | lib/sqlite/System.Data.SQLite.dll 14 | *.orig 15 | *.zip 16 | Samples/DataBus/storage 17 | packages 18 | PrecompiledWeb 19 | tempstorage 20 | core-only 21 | Release 22 | Artifacts 23 | LogFiles 24 | csx 25 | *.ncrunchproject 26 | *.ncrunchsolution 27 | _NCrunch_NServiceBus/* 28 | logs 29 | run-git.cmd 30 | src/Chocolatey/Build/* 31 | 32 | installer/[F|f]iles 33 | installer/[C|c]ustom[A|a]ctions 34 | installer/ServiceControl-cache 35 | 36 | # Created by https://www.gitignore.io 37 | 38 | ### VisualStudio ### 39 | ## Ignore Visual Studio temporary files, build results, and 40 | ## files generated by popular Visual Studio add-ons. 41 | 42 | # User-specific files 43 | *.suo 44 | *.user 45 | *.userosscache 46 | *.sln.docstates 47 | .vs/ 48 | 49 | # mac temp file ignore 50 | .DS_Store 51 | 52 | # Build results 53 | [Dd]ebug/ 54 | [Dd]ebugPublic/ 55 | [Rr]elease/ 56 | [Rr]eleases/ 57 | x64/ 58 | x86/ 59 | build/ 60 | bld/ 61 | [Bb]in/ 62 | [Oo]bj/ 63 | [Aa]ssets/ 64 | 65 | # Roslyn cache directories 66 | *.ide/ 67 | 68 | # MSTest test Results 69 | [Tt]est[Rr]esult*/ 70 | [Bb]uild[Ll]og.* 71 | 72 | #NUNIT 73 | *.VisualState.xml 74 | TestResult.xml 75 | 76 | # NCrunch 77 | _NCrunch_* 78 | .*crunch*.local.xml 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper*/ 82 | *.[Rr]e[Ss]harper 83 | *.DotSettings.user 84 | 85 | src/scaffolding.config 86 | 87 | # Approval tests temp file 88 | *.received.* 89 | 90 | # JetBrains Rider 91 | .idea/ 92 | *.sln.iml -------------------------------------------------------------------------------- /.reposync.yml: -------------------------------------------------------------------------------- 1 | ignore: true 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | For information on contributing, see https://docs.particular.net/platform/contributing. 2 | -------------------------------------------------------------------------------- /GitReleaseManager.yaml: -------------------------------------------------------------------------------- 1 | create: 2 | include-footer: true 3 | footer-heading: Where to get it 4 | footer-content: You can download this release from our [website](http://particular.net/downloads). 5 | issue-labels-include: 6 | - "Type: Bug" 7 | - "Type: Feature" 8 | - "Type: Improvement" 9 | issue-labels-exclude: 10 | - "Type: Misc" 11 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | By accessing NServiceBus code here, you are agreeing to the following licensing terms. 2 | If you do not agree to these terms, do not access the NServiceBus code. 3 | 4 | Your license to the NServiceBus source and/or binaries is governed by the Reciprocal Public License 1.5 (RPL1.5) license as described here: 5 | 6 | https://www.opensource.org/licenses/rpl1.5.txt 7 | 8 | If you do not wish to release the source of software you build using NServiceBus, you may use NServiceBus source and/or binaries under the License Agreement described here: 9 | 10 | https://particular.net/LicenseAgreement 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## NServiceBus.PowerShell 2 | 3 | NServiceBus.PowerShell provides a powershell extension for NServiceBus. It sets up a computer to run NServiceBus by providing a set of cmdlets. 4 | 5 | It is tool for managing operations for users of the [Particular Service Platform](https://particular.net/service-platform), which includes [NServiceBus](https://particular.net/nservicebus) and tools to build, monitor, and debug distributed systems. 6 | 7 | See the [Management using PowerShell documentation](https://docs.particular.net/nservicebus/operations/management-using-powershell) for more details on how to use it. 8 | 9 | ## Building 10 | 11 | To build NServiceBus.PowerShell just open `NServiceBus.Powershell.sln` in Visual Studio. 12 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Custom.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | false 5 | false 6 | 7 | 8 | 9 | 6.0 10 | minor 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | true 7 | 8 | 9 | 10 | true 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell.CustomActions/CustomAction.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell.CustomActions/CustomAction.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell.CustomActions 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Runtime.InteropServices; 6 | using Microsoft.Deployment.WindowsInstaller; 7 | 8 | public class CustomAction 9 | { 10 | const string PSModulePath = "PSMODULEPATH"; 11 | 12 | [DllImport("User32.DLL")] 13 | static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam); 14 | 15 | [CustomAction] 16 | public static ActionResult AddToPSModuleEnvironmentVar(Session session) 17 | { 18 | //Advanced Installer doesn't notify of environment changes on system environment variables 19 | var appDir = session["PowerShellModules_Dir"]; 20 | 21 | var environmentVariable = Environment.GetEnvironmentVariable(PSModulePath, EnvironmentVariableTarget.Machine); 22 | if (environmentVariable != null) 23 | { 24 | var parts = environmentVariable.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList(); 25 | if (!parts.Any(p => p.Equals(appDir, StringComparison.OrdinalIgnoreCase))) 26 | { 27 | parts.Add(appDir); 28 | var newValue = string.Join(";", parts); 29 | Environment.SetEnvironmentVariable(PSModulePath, newValue, EnvironmentVariableTarget.Machine); 30 | } 31 | } 32 | return ActionResult.Success; 33 | } 34 | 35 | [CustomAction] 36 | public static ActionResult RemoveFromPSModuleEnvironmentVar(Session session) 37 | { 38 | //Advanced Installer doesn't notify of environment changes on system environment variables 39 | var appDir = session["PowerShellModules_Dir"]; 40 | if (appDir.EndsWith(@"\")) 41 | { 42 | appDir = appDir.Remove(appDir.Length - 1); 43 | } 44 | 45 | var environmentVariable = Environment.GetEnvironmentVariable(PSModulePath, EnvironmentVariableTarget.Machine); 46 | if (environmentVariable != null) 47 | { 48 | var parts = environmentVariable.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList(); 49 | if (parts.Any(p => p.Equals(appDir, StringComparison.OrdinalIgnoreCase))) 50 | { 51 | var newParts = parts.Where(p => !p.Equals(appDir, StringComparison.OrdinalIgnoreCase)).ToList(); 52 | var newValue = string.Join(";", newParts); 53 | Environment.SetEnvironmentVariable(PSModulePath, newValue, EnvironmentVariableTarget.Machine); 54 | } 55 | } 56 | return ActionResult.Success; 57 | } 58 | 59 | static void Log(Session session, string message, params object[] args) 60 | { 61 | LogAction(session, string.Format(message, args)); 62 | } 63 | 64 | public static Action LogAction = (s, m) => s.Log(m); 65 | 66 | public static Func GetAction = (s, key) => s[key]; 67 | 68 | public static Action SetAction = (s, key, value) => s[key] = value; 69 | } 70 | 71 | public static class SessionExtensions 72 | { 73 | public static string Get(this Session session, string key) 74 | { 75 | return CustomAction.GetAction(session, key); 76 | } 77 | 78 | public static void Set(this Session session, string key, string value) 79 | { 80 | CustomAction.SetAction(session, key, value); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell.CustomActions/NServiceBus.PowerShell.CustomActions.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net40 5 | true 6 | ..\NServiceBus.snk 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | NServiceBus.PowerShell.CustomActions.CA.dll 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell.Tests/MsmqSetupTests.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell.Tests 2 | { 3 | using System.Diagnostics; 4 | using NUnit.Framework; 5 | 6 | 7 | [TestFixture] 8 | public class MsmqSetupTests 9 | { 10 | [Explicit] 11 | [Test] 12 | public void IsMsmqInstalled() 13 | { 14 | Debug.WriteLine(new MsmqSetup().IsMsmqInstalled()); 15 | } 16 | [Explicit] 17 | [Test] 18 | public void IsInstallationGood() 19 | { 20 | Debug.WriteLine(new MsmqSetup().IsInstallationGood()); 21 | } 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell.Tests/NServiceBus.PowerShell.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452 5 | Library 6 | true 7 | ..\NServiceBus.snk 8 | NServiceBus.PowerShell.Tests 9 | NServiceBus.PowerShell.Tests 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell.Tests/PerformanceCounterSetupTests.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell.Tests 2 | { 3 | using System.Diagnostics; 4 | using NUnit.Framework; 5 | 6 | 7 | [TestFixture] 8 | public class PerformanceCounterSetupTests 9 | { 10 | 11 | [SetUp] 12 | public void Setup() 13 | { 14 | 15 | PerformanceCounter.CloseSharedResources(); 16 | if (PerformanceCounterCategory.Exists("NServiceBus")) 17 | { 18 | new PerformanceCounterSetup().DeleteCategory(); 19 | } 20 | } 21 | 22 | [TearDown] 23 | public void TearDown() 24 | { 25 | PerformanceCounter.CloseSharedResources(); 26 | if (PerformanceCounterCategory.Exists("NServiceBus")) 27 | { 28 | new PerformanceCounterSetup().DeleteCategory(); 29 | } 30 | } 31 | 32 | 33 | [Explicit] 34 | [Test] 35 | public void DoAllCountersExist_returns_false_when_category_missing() 36 | { 37 | Assert.IsFalse(new PerformanceCounterSetup().CheckCounters()); 38 | } 39 | 40 | [Explicit] 41 | [Test] 42 | public void DoAllCountersExist_returns_true_when_all_exist() 43 | { 44 | new PerformanceCounterSetup().SetupCounters(); 45 | PerformanceCounter.CloseSharedResources(); 46 | Assert.IsTrue(new PerformanceCounterSetup().CheckCounters()); 47 | } 48 | 49 | [Explicit] 50 | [Test] 51 | public void DoAllCountersExist_returns_false_when_some_counters_are_missing_exist() 52 | { 53 | var counters = new CounterCreationDataCollection 54 | { 55 | new CounterCreationData("Critical Time","Age of the oldest message in the queue.",PerformanceCounterType.NumberOfItems32), 56 | }; 57 | PerformanceCounterCategory.Create("NServiceBus", "NServiceBus statistics", PerformanceCounterCategoryType.MultiInstance, counters); 58 | PerformanceCounter.CloseSharedResources(); 59 | Assert.IsFalse(new PerformanceCounterSetup().CheckCounters()); 60 | } 61 | 62 | [Explicit] 63 | [Test] 64 | public void CreateBadCounters() 65 | { 66 | var counters = new CounterCreationDataCollection 67 | { 68 | new CounterCreationData("Critical Time","Age of the oldest message in the queue.",PerformanceCounterType.NumberOfItems32), 69 | }; 70 | PerformanceCounterCategory.Create("NServiceBus", "NServiceBus statistics", PerformanceCounterCategoryType.MultiInstance, counters); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell.Tests/RegistryHelperTests.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell.Tests 2 | { 3 | using System; 4 | using System.Globalization; 5 | using System.Text; 6 | using Helpers; 7 | using Microsoft.Win32; 8 | using NUnit.Framework; 9 | using RegistryView = Helpers.RegistryView; 10 | 11 | [TestFixture] 12 | public class RegistryHelperTests 13 | { 14 | const string testkey = @"Software\ParticularSoftware-Test"; 15 | 16 | [SetUp] 17 | public void Setup() 18 | { 19 | RegistryHelper.CurrentUser(RegistryView.Default).DeleteKeyTree(testkey); 20 | } 21 | 22 | [Test] 23 | public void KeyExistsTest() 24 | { 25 | var hklm = RegistryHelper.LocalMachine(RegistryView.Default); 26 | Assert.IsTrue(hklm.KeyExists(@"Software\Microsoft"), @"KeyExists should be true for Software\Microsoft"); 27 | Assert.IsFalse(hklm.KeyExists(@"Software\BogusRegistryEntry"), @"KeyExists should be false for Software\BogusRegistryEntry"); 28 | } 29 | 30 | [Test] 31 | public void TestSubKeyFunctions() 32 | { 33 | var hkcu = RegistryHelper.CurrentUser(RegistryView.Default); 34 | hkcu.CreateSubkey(testkey); 35 | Assert.IsTrue(hkcu.KeyExists(testkey), "Failed to create or verify test reg key"); 36 | } 37 | 38 | [Test] 39 | public void TestReadAndWriteString() 40 | { 41 | const string valueName = "teststring"; 42 | var hkcu = RegistryHelper.CurrentUser(RegistryView.Default); 43 | var ticks = DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture); 44 | hkcu.WriteValue(testkey, valueName, ticks, RegistryValueKind.String); 45 | var val = (string)hkcu.ReadValue(testkey, valueName, null, true); 46 | Assert.IsTrue(string.Equals(val, ticks), "The written string does match what was read"); 47 | Assert.IsTrue(hkcu.GetRegistryValueKind(testkey, valueName) == RegistryValueKind.String, "Failed to assert that written data was a string"); 48 | 49 | } 50 | 51 | [Test] 52 | public void TestReadAndWriteBinary() 53 | { 54 | const string valueName = "testbinary"; 55 | var hkcu = RegistryHelper.CurrentUser(RegistryView.Default); 56 | var ticks = Encoding.Unicode.GetBytes(DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture)); 57 | hkcu.WriteValue(testkey, valueName, ticks, RegistryValueKind.Binary); 58 | var val = (byte[])hkcu.ReadValue(testkey, valueName, null, true); 59 | Assert.IsTrue(BytesMatch(ticks, val), "The written byte array does match what was read"); 60 | Assert.IsTrue(hkcu.GetRegistryValueKind(testkey, valueName) == RegistryValueKind.Binary, "Failed to assert that written data was binary"); 61 | 62 | } 63 | 64 | [Test] 65 | public void TestReadAndWriteDWord() 66 | { 67 | const string valueName = "testdword"; 68 | var hkcu = RegistryHelper.CurrentUser(RegistryView.Default); 69 | var num = 1 + DateTime.Now.Millisecond; 70 | hkcu.WriteValue(testkey, valueName, num, RegistryValueKind.DWord); 71 | var val = (int)hkcu.ReadValue(testkey, valueName, null, true); 72 | Assert.IsTrue(num == val, "The written dword does match what was read"); 73 | Assert.IsTrue(hkcu.GetRegistryValueKind(testkey, valueName) == RegistryValueKind.DWord, "Failed to assert that written data was a dword"); 74 | } 75 | 76 | [Test] 77 | public void TestDeleteValue() 78 | { 79 | const string valueName = "delete-me"; 80 | var hkcu = RegistryHelper.CurrentUser(RegistryView.Default); 81 | hkcu.WriteValue(testkey, valueName, "test", RegistryValueKind.String); 82 | Assert.IsTrue(hkcu.ValueExists(testkey, valueName), "Failed to assert that value exists "); 83 | hkcu.DeleteValue(testkey, valueName); 84 | Assert.IsFalse(hkcu.ValueExists(testkey, valueName), "Failed to assert that value was deleted"); 85 | Assert.IsTrue(hkcu.DeleteValue(testkey, "I_Should_Not_Be_Present"), "Deletion of a non-existent value should return true"); 86 | } 87 | 88 | [TearDown] 89 | public void TearDown() 90 | { 91 | RegistryHelper.CurrentUser(RegistryView.Default).DeleteKeyTree(testkey); 92 | } 93 | 94 | static bool BytesMatch(byte[] x, byte[] y) 95 | { 96 | if (x.Length != y.Length) return false; 97 | for (var i = 0; i < x.Length; i++) 98 | { 99 | if (x[i] != y[i]) 100 | return false; 101 | } 102 | return true; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.1.32328.378 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NServiceBus.PowerShell", "NServiceBus.PowerShell\NServiceBus.PowerShell.csproj", "{5E51EFBF-329F-4D3A-B86E-CC111697746F}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NServiceBus.PowerShell.Tests", "NServiceBus.PowerShell.Tests\NServiceBus.PowerShell.Tests.csproj", "{04121C4B-EB4F-4508-8760-5818185F4403}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NServiceBus.PowerShell.CustomActions", "NServiceBus.PowerShell.CustomActions\NServiceBus.PowerShell.CustomActions.csproj", "{CA37BC61-5B97-456A-ABEF-86A157582A85}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Setup", "Setup\Setup.csproj", "{F6473A7A-01B7-4A9A-B30C-4D200BFFFE4D}" 13 | ProjectSection(ProjectDependencies) = postProject 14 | {CA37BC61-5B97-456A-ABEF-86A157582A85} = {CA37BC61-5B97-456A-ABEF-86A157582A85} 15 | {5E51EFBF-329F-4D3A-B86E-CC111697746F} = {5E51EFBF-329F-4D3A-B86E-CC111697746F} 16 | EndProjectSection 17 | EndProject 18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Installer", "Installer", "{CA92F8D6-C6E1-4E63-A517-0ACE22137081}" 19 | EndProject 20 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{90713D38-E2A0-45E7-8AA4-2404EA1F684B}" 21 | ProjectSection(SolutionItems) = preProject 22 | Custom.Build.props = Custom.Build.props 23 | EndProjectSection 24 | EndProject 25 | Global 26 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 27 | Debug|Any CPU = Debug|Any CPU 28 | Release|Any CPU = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 31 | {5E51EFBF-329F-4D3A-B86E-CC111697746F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {5E51EFBF-329F-4D3A-B86E-CC111697746F}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {5E51EFBF-329F-4D3A-B86E-CC111697746F}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {5E51EFBF-329F-4D3A-B86E-CC111697746F}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {04121C4B-EB4F-4508-8760-5818185F4403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {04121C4B-EB4F-4508-8760-5818185F4403}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {04121C4B-EB4F-4508-8760-5818185F4403}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {04121C4B-EB4F-4508-8760-5818185F4403}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {CA37BC61-5B97-456A-ABEF-86A157582A85}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {CA37BC61-5B97-456A-ABEF-86A157582A85}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {CA37BC61-5B97-456A-ABEF-86A157582A85}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {CA37BC61-5B97-456A-ABEF-86A157582A85}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {F6473A7A-01B7-4A9A-B30C-4D200BFFFE4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {F6473A7A-01B7-4A9A-B30C-4D200BFFFE4D}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {F6473A7A-01B7-4A9A-B30C-4D200BFFFE4D}.Release|Any CPU.Build.0 = Release|Any CPU 46 | EndGlobalSection 47 | GlobalSection(SolutionProperties) = preSolution 48 | HideSolutionNode = FALSE 49 | EndGlobalSection 50 | GlobalSection(NestedProjects) = preSolution 51 | {CA37BC61-5B97-456A-ABEF-86A157582A85} = {CA92F8D6-C6E1-4E63-A517-0ACE22137081} 52 | {F6473A7A-01B7-4A9A-B30C-4D200BFFFE4D} = {CA92F8D6-C6E1-4E63-A517-0ACE22137081} 53 | EndGlobalSection 54 | GlobalSection(ExtensibilityGlobals) = postSolution 55 | SolutionGuid = {D23C6E09-DA1C-486D-BEFB-3AA29520A542} 56 | EndGlobalSection 57 | EndGlobal 58 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Cmdlets/CmdletBase.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell 2 | { 3 | using System.Management.Automation; 4 | using System.Security; 5 | 6 | public abstract class CmdletBase : PSCmdlet 7 | { 8 | protected override void BeginProcessing() 9 | { 10 | var processUtil = new ProcessUtil(Host); 11 | if (!processUtil.IsRunningWithElevatedPrivileges()) 12 | { 13 | var exception = new SecurityException("This command requires elevated privileges"); 14 | ThrowTerminatingError(new ErrorRecord(exception, null, ErrorCategory.PermissionDenied, null)); 15 | } 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Cmdlets/CmdletHelperBase.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell 2 | { 3 | using System; 4 | using System.Management.Automation.Host; 5 | 6 | public abstract class CmdletHelperBase 7 | { 8 | internal PSHost Host { get; set; } 9 | 10 | protected CmdletHelperBase() 11 | { 12 | 13 | } 14 | 15 | protected CmdletHelperBase(PSHost host) 16 | { 17 | Host = host; 18 | } 19 | 20 | internal void WriteLine(string message, params object[] args) 21 | { 22 | if (Host != null) 23 | { 24 | Host.UI.WriteLine(string.Format(message, args)); 25 | } 26 | else 27 | { 28 | Console.WriteLine(message, args); 29 | } 30 | } 31 | 32 | internal void WriteVerbose(string message, params object[] args) 33 | { 34 | if (Host != null) 35 | { 36 | Host.UI.WriteVerboseLine(string.Format(message, args)); 37 | } 38 | else 39 | { 40 | Console.WriteLine("VERBOSE: " + message, args); 41 | } 42 | } 43 | 44 | internal void WriteWarning(string message, params object[] args) 45 | { 46 | if (Host != null) 47 | { 48 | Host.UI.WriteWarningLine(string.Format(message, args)); 49 | } 50 | else 51 | { 52 | Console.WriteLine("WARNING: " + message, args); 53 | } 54 | } 55 | 56 | internal void WriteError(string message, params object[] args) 57 | { 58 | if (Host != null) 59 | { 60 | Host.UI.WriteWarningLine(string.Format(message, args)); 61 | } 62 | else 63 | { 64 | Console.WriteLine("ERROR: " + message, args); 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Cmdlets/GetNServiceBusLocalMachineSettings.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Management.Automation; 6 | using Cmdlets; 7 | using Helpers; 8 | 9 | [Cmdlet(VerbsCommon.Get, "NServiceBusLocalMachineSettings")] 10 | public class GetNServiceBusLocalMachineSettings : CmdletBase 11 | { 12 | List results = new List(); 13 | 14 | protected override void ProcessRecord() 15 | { 16 | const string key = @"SOFTWARE\ParticularSoftware\ServiceBus"; 17 | 18 | if (EnvironmentHelper.Is64BitOperatingSystem) 19 | { 20 | var key64Exists = (RegistryHelper.LocalMachine(RegistryView.Registry64).KeyExists(key)); 21 | var result64 = new MachineSettingsResult 22 | { 23 | Registry = "64 bit", 24 | AuditQueue = key64Exists ? (string)RegistryHelper.LocalMachine(RegistryView.Registry64).ReadValue(key, "AuditQueue", null, false) : null, 25 | ErrorQueue = key64Exists ? (string)RegistryHelper.LocalMachine(RegistryView.Registry64).ReadValue(key, "ErrorQueue", null, false) : null 26 | }; 27 | results.Add(result64); 28 | } 29 | 30 | var key32Exists = (RegistryHelper.LocalMachine(RegistryView.Registry32).KeyExists(key)); 31 | var result32 = new MachineSettingsResult 32 | { 33 | Registry = "32 bit", 34 | AuditQueue = key32Exists ? (string)RegistryHelper.LocalMachine(RegistryView.Registry32).ReadValue(key, "AuditQueue", null, false) : null, 35 | ErrorQueue = key32Exists ? (string)RegistryHelper.LocalMachine(RegistryView.Registry32).ReadValue(key, "ErrorQueue", null, false) : null 36 | }; 37 | results.Add(result32); 38 | 39 | if (results.Count == 2) 40 | { 41 | if (string.Compare(results[0].AuditQueue, results[1].AuditQueue, StringComparison.OrdinalIgnoreCase) != 0) 42 | { 43 | WriteWarning("AuditQueue value is different for 32 bit and 64 bit applications"); 44 | } 45 | 46 | if (string.Compare(results[0].ErrorQueue, results[1].ErrorQueue, StringComparison.OrdinalIgnoreCase) != 0) 47 | { 48 | WriteWarning("ErrorQueue value is different for 32 bit and 64 bit applications"); 49 | } 50 | } 51 | 52 | foreach (var result in results) 53 | { 54 | WriteObject(result); 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Cmdlets/InstallDtc.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell 2 | { 3 | using System; 4 | using System.Management.Automation; 5 | using Helpers; 6 | using System.Text.RegularExpressions; 7 | 8 | [Cmdlet(VerbsLifecycle.Install, "NServiceBusDTC", SupportsShouldProcess = true)] 9 | [Obsolete(WarningMessage)] 10 | public class InstallDtc : CmdletBase 11 | { 12 | const string WarningMessage = "Installing DTC is supported natively by PowerShell. See https://docs.particular.net/search?q=powershell+dtc."; 13 | 14 | [Parameter(Mandatory = false, HelpMessage = "Port Range to use for DCOM Config. The format should be two numbers separated by a dash. e.g. \"5000-6000\"")] 15 | public string PortRange { get; set; } 16 | 17 | protected override void ProcessRecord() 18 | { 19 | WriteWarning(WarningMessage); 20 | 21 | if (!StringExtensions.IsNullOrWhiteSpace(PortRange)) 22 | { 23 | var portRangeRegex = new Regex(@"^[0-9]+\-[0-9]+$"); 24 | var match = portRangeRegex.Match(PortRange); 25 | if (!match.Success) ThrowTerminatingError(new ErrorRecord(new Exception("Invalid value for PortRange parameter. The format should be two numbers separated by a dash. e.g. \"5000-6000\""), "1", ErrorCategory.InvalidArgument, "")); 26 | } 27 | 28 | if (ShouldProcess(EnvironmentHelper.MachineName)) 29 | { 30 | new DtcSetup(Host).StartDtcIfNecessary(PortRange); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Cmdlets/InstallMsmq.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell 2 | { 3 | using System.Management.Automation; 4 | 5 | [Cmdlet(VerbsLifecycle.Install, "NServiceBusMSMQ")] 6 | public class InstallMsmq : CmdletBase 7 | { 8 | protected override void ProcessRecord() 9 | { 10 | var msmqIsGood = new MsmqSetup(Host).StartMsmqIfNecessary(); 11 | 12 | if (!msmqIsGood) 13 | { 14 | WriteWarning("MSMQ may need to be reinstalled manually. Please ensure MSMQ is running properly."); 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Cmdlets/InstallPerformanceCounters.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell 2 | { 3 | using System; 4 | using System.Management.Automation; 5 | 6 | [Cmdlet(VerbsLifecycle.Install, "NServiceBusPerformanceCounters")] 7 | public class InstallPerformanceCounters : CmdletBase 8 | { 9 | // ReSharper disable MemberCanBePrivate.Global 10 | [Parameter(Mandatory = false, HelpMessage = "Force re-creation of performance counters if they already exist.")] 11 | public SwitchParameter Force { get; set; } 12 | 13 | protected override void BeginProcessing() 14 | { 15 | WriteWarning("This cmdlet is obsolete. Performance counter registration is now handled via the NServiceBus.Metrics.PerformanceCounters nuget package. For legacy installations this cmdlet can still be used. Please refer to the NServiceBus.Metrics.PerformanceCounters documentation for further information"); 16 | } 17 | 18 | // ReSharper enable MemberCanBePrivate.Global 19 | protected override void ProcessRecord() 20 | { 21 | if (Force) 22 | { 23 | ForceCreate(); 24 | } 25 | else 26 | { 27 | Create(); 28 | } 29 | } 30 | 31 | void Create() 32 | { 33 | var setup = new PerformanceCounterSetup(Host); 34 | var allCountersExist = setup.CheckCounters(); 35 | if (allCountersExist) 36 | { 37 | return; 38 | } 39 | 40 | if (setup.DoesCategoryExist()) 41 | { 42 | var exception = new Exception("Existing category is not configured correctly. Use the -Force option to delete and re-create"); 43 | var errorRecord = new ErrorRecord(exception, "FailedToCreateCategory", ErrorCategory.NotSpecified, null); 44 | ThrowTerminatingError(errorRecord); 45 | } 46 | setup.SetupCounters(); 47 | } 48 | 49 | void ForceCreate() 50 | { 51 | var setup = new PerformanceCounterSetup(Host); 52 | try 53 | { 54 | setup.DeleteCategory(); 55 | } 56 | catch (Exception exception) 57 | { 58 | var errorRecord = new ErrorRecord(exception, "FailedToDeleteCategory", ErrorCategory.NotSpecified, null); 59 | ThrowTerminatingError(errorRecord); 60 | } 61 | setup.SetupCounters(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Cmdlets/InstallPlatformLicense.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell.Cmdlets 2 | { 3 | using System; 4 | using System.IO; 5 | using System.Management.Automation; 6 | using Microsoft.PowerShell.Commands; 7 | using Microsoft.Win32; 8 | using Helpers; 9 | using RegistryView = Helpers.RegistryView; 10 | 11 | [Cmdlet(VerbsLifecycle.Install, "NServiceBusPlatformLicense", DefaultParameterSetName = "ByLicenseFile")] 12 | [Obsolete(@"Installing license information in the registry has been deprecated as the Particular Platform reads license info from file system. For legacy installations this cmdlet can still be used. See https://docs.particular.net/search?q=license.")] 13 | public class InstallPlatformLicense : CmdletBase 14 | { 15 | [Parameter(Mandatory = true, HelpMessage = "Platform license file to import", Position = 0, ParameterSetName = "ByLicenseFile")] 16 | [ValidateNotNullOrEmpty] 17 | public string LicenseFile { get; set; } 18 | 19 | [Parameter(Mandatory = true, HelpMessage = "Platform license string to import", Position = 0, ParameterSetName = "ByLicenseString")] 20 | [ValidateNotNullOrEmpty] 21 | public string LicenseString { get; set; } 22 | 23 | protected override void BeginProcessing() 24 | { 25 | WriteWarning("Installing license information in the registry has been deprecated as the Particular Platform reads license info from file system. For legacy installations this cmdlet can still be used. See https://docs.particular.net/search?q=license."); 26 | } 27 | 28 | protected override void ProcessRecord() 29 | { 30 | const string particular = @"Software\ParticularSoftware"; 31 | string content; 32 | 33 | // LicenseFile primary option 34 | if (ParameterSetName.Equals("ByLicenseFile")) 35 | { 36 | ProviderInfo provider; 37 | PSDriveInfo drive; 38 | var psPath = SessionState.Path.GetUnresolvedProviderPathFromPSPath(LicenseFile, out provider, out drive); 39 | 40 | 41 | if (provider.ImplementingType != typeof(FileSystemProvider)) 42 | { 43 | var ex = new ArgumentException($"{psPath} does not resolve to a path on the FileSystem provider."); 44 | var error = new ErrorRecord(ex, "InvalidProvider", ErrorCategory.InvalidArgument, psPath); 45 | WriteError(error); 46 | return; 47 | } 48 | 49 | content = File.ReadAllText(psPath); 50 | if (!CheckFileContentIsALicenseFile(content)) 51 | { 52 | var ex = new InvalidDataException($"{psPath} is not a valid license file"); 53 | var error = new ErrorRecord(ex, "InvalidLicense", ErrorCategory.InvalidData, psPath); 54 | WriteError(error); 55 | return; 56 | } 57 | } 58 | // LicenseString secondary option 59 | else 60 | { 61 | content = LicenseString; 62 | if (!CheckFileContentIsALicenseFile(content)) 63 | { 64 | var ex = new InvalidDataException("The supplied LicenseString is not a valid license file"); 65 | var error = new ErrorRecord(ex, "InvalidLicense", ErrorCategory.InvalidData, null); 66 | WriteError(error); 67 | return; 68 | } 69 | } 70 | 71 | if (EnvironmentHelper.Is64BitOperatingSystem) 72 | { 73 | RegistryHelper.LocalMachine(RegistryView.Registry64).WriteValue(particular, "License", content, RegistryValueKind.String); 74 | } 75 | RegistryHelper.LocalMachine(RegistryView.Registry32).WriteValue(particular, "License", content, RegistryValueKind.String); 76 | } 77 | 78 | bool CheckFileContentIsALicenseFile(string content) 79 | { 80 | return (content.Contains(" 24 | /// Checks that the MSDTC service is running and configured correctly, and if not 25 | /// takes the necessary corrective actions to make it so. 26 | /// 27 | public void StartDtcIfNecessary(string PortRange = null) 28 | { 29 | var processUtil = new ProcessUtil(Host); 30 | 31 | if (DoesSecurityConfigurationRequireRestart(true, PortRange)) 32 | { 33 | processUtil.ChangeServiceStatus(Controller, ServiceControllerStatus.Stopped, Controller.Stop); 34 | } 35 | 36 | processUtil.ChangeServiceStatus(Controller, ServiceControllerStatus.Running, Controller.Start); 37 | } 38 | 39 | public bool IsDtcWorking() 40 | { 41 | 42 | if (DoesSecurityConfigurationRequireRestart(false)) 43 | { 44 | return false; 45 | } 46 | 47 | if (Controller.Status != ServiceControllerStatus.Running) 48 | { 49 | WriteWarning("MSDTC isn't currently running and needs to be started"); 50 | return false; 51 | } 52 | 53 | return true; 54 | } 55 | 56 | bool DoesSecurityConfigurationRequireRestart(bool doChanges, string PortRange = null) 57 | { 58 | var regview = EnvironmentHelper.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Default; 59 | var hklm = RegistryHelper.LocalMachine(regview); 60 | 61 | const string keyName = @"SOFTWARE\Microsoft\MSDTC\Security"; 62 | var requireRestart = false; 63 | foreach (var val in RegValues) 64 | { 65 | if ((int)hklm.ReadValue(keyName, val, 0, true) != 0) 66 | { 67 | continue; 68 | } 69 | 70 | if (doChanges) 71 | { 72 | WriteWarning("DTC not configured correctly. Going to fix. This will require a restart of the DTC service."); 73 | if (!hklm.WriteValue(keyName, val, 1, RegistryValueKind.DWord)) 74 | { 75 | throw new Exception($"Failed to set value '{val}' to '1' in '{keyName}'"); 76 | } 77 | WriteWarning("DTC configuration was fixed."); 78 | } 79 | requireRestart = true; 80 | } 81 | 82 | 83 | if (!StringExtensions.IsNullOrWhiteSpace(PortRange)) 84 | { 85 | const string rpcKeyName = @"SOFTWARE\Microsoft\Rpc\Internet"; 86 | 87 | if (!hklm.KeyExists(rpcKeyName)) 88 | { 89 | if (doChanges) 90 | { 91 | hklm.CreateSubkey(rpcKeyName); 92 | WriteWarning("RPC Port configuration was fixed."); 93 | } 94 | requireRestart = true; 95 | } 96 | 97 | foreach (var val in RpcRegValues) 98 | { 99 | if ((string)hklm.ReadValue(rpcKeyName, val, "N", true) == "Y") 100 | { 101 | continue; 102 | } 103 | 104 | if (doChanges) 105 | { 106 | WriteWarning("RPC Ports not configured correctly. Going to fix. This will require a restart of the DTC service."); 107 | if (!hklm.WriteValue(rpcKeyName, val, "Y", RegistryValueKind.String)) 108 | { 109 | throw new Exception($"Failed to set value '{val}' to 'Y' in '{rpcKeyName}'"); 110 | } 111 | WriteWarning("RPC Port configuration was fixed."); 112 | } 113 | requireRestart = true; 114 | } 115 | 116 | const string RpcPortsKey = "Ports"; 117 | string[] RpcPortsArray = 118 | { 119 | PortRange 120 | }; 121 | 122 | if (Array.IndexOf((string[])hklm.ReadValue(rpcKeyName, RpcPortsKey, new string[] { }, true), PortRange) >= 0) 123 | { 124 | return requireRestart; 125 | } 126 | 127 | if (doChanges) 128 | { 129 | WriteWarning("RPC Ports not configured correctly. Going to fix. This will require a restart of the DTC service."); 130 | if (!hklm.WriteValue(rpcKeyName, RpcPortsKey, RpcPortsArray, RegistryValueKind.MultiString)) 131 | { 132 | throw new Exception($"Failed to set value '{RpcPortsKey}' in '{rpcKeyName}'"); 133 | } 134 | WriteWarning("RPC Port configuration was fixed."); 135 | } 136 | requireRestart = true; 137 | } 138 | 139 | return requireRestart; 140 | } 141 | 142 | static readonly ServiceController Controller = new ServiceController { ServiceName = "MSDTC", MachineName = "." }; 143 | static readonly List RegValues = new List(new[] { "NetworkDtcAccess", "NetworkDtcAccessOutbound", "NetworkDtcAccessTransactions", "XaTransactions" }); 144 | static readonly List RpcRegValues = new List(new[] { "PortsInternetAvailable", "UseInternetPorts" }); 145 | } 146 | } -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Formats/NServiceBus.PowerShell.Cmdlets.InstallationResult.format.ps1xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | installresult 6 | 7 | NServiceBus.Powershell.Cmdlets.InstallationResult 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Message 16 | 17 | 18 | 19 | Installed 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Formats/NServiceBus.PowerShell.Cmdlets.MachineSettingsResult.format.ps1xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | machineresult 6 | 7 | NServiceBus.Powershell.Cmdlets.MachineSettingsResult 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Registry 16 | 17 | 18 | 19 | AuditQueue 20 | 21 | 22 | 23 | ErrorQueue 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Helpers/Action.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell 2 | { 3 | public delegate void Action(); 4 | } -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Helpers/EnvironmentHelper.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell.Helpers 2 | { 3 | using System; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | 7 | /// 8 | /// Mimics some of the items found in .Net 4 that are missing form .net System.Environment 9 | /// 10 | internal class EnvironmentHelper 11 | { 12 | const int MaxMachineNameLength = 256; 13 | 14 | [DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] 15 | [return: MarshalAs(UnmanagedType.Bool)] 16 | static extern bool IsWow64Process( 17 | [In] 18 | IntPtr hSourceProcessHandle, 19 | [Out, MarshalAs(UnmanagedType.Bool)] 20 | out bool isWow64); 21 | 22 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 23 | static extern IntPtr GetModuleHandle(string moduleName); 24 | 25 | [DllImport("kernel32.dll", CharSet = CharSet.Ansi, BestFitMapping = false, SetLastError = true, ExactSpelling = true)] 26 | static extern IntPtr GetProcAddress(IntPtr hModule, string methodName); 27 | 28 | [DllImport("kernel32", CharSet = CharSet.Auto, BestFitMapping = false)] 29 | static extern int GetComputerName([Out] StringBuilder nameBuffer, ref int bufferSize); 30 | 31 | public static bool DoesWin32MethodExist(string moduleName, string methodName) 32 | { 33 | var hModule = GetModuleHandle(moduleName); 34 | if (hModule == IntPtr.Zero) 35 | { 36 | return false; 37 | } 38 | var functionPointer = GetProcAddress(hModule, methodName); 39 | return (functionPointer != IntPtr.Zero); 40 | } 41 | 42 | public static bool Is64BitOperatingSystem 43 | { 44 | get 45 | { 46 | #if WIN32 47 | bool isWow64; 48 | return DoesWin32MethodExist("Kernel32.dll", "IsWow64Process") 49 | && IsWow64Process(Process.GetCurrentProcess().Handle, out isWow64) 50 | && isWow64; 51 | #else 52 | return true; 53 | #endif 54 | } 55 | } 56 | 57 | public static string MachineName 58 | { 59 | get 60 | { 61 | var buf = new StringBuilder(MaxMachineNameLength); 62 | var len = MaxMachineNameLength; 63 | if (GetComputerName(buf, ref len) == 0) 64 | throw new InvalidOperationException("InvalidOperation ComputerName"); 65 | return buf.ToString(); 66 | } 67 | } 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Helpers/ExtensionAttribute.cs: -------------------------------------------------------------------------------- 1 | namespace System.Runtime.CompilerServices 2 | { 3 | /// 4 | /// Simple Trick to get Extension methods in .Net 2 5 | /// See : http://csharpindepth.com/Articles/Chapter1/Versions.aspx 6 | /// 7 | [AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)] 8 | public class ExtensionAttribute : Attribute 9 | { 10 | } 11 | } -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Helpers/HeaderInfo.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell 2 | { 3 | using System; 4 | 5 | /// 6 | /// Represents the structure of header information passed in a TransportMessage. 7 | /// 8 | [Serializable] 9 | public class HeaderInfo 10 | { 11 | /// 12 | /// The key used to lookup the value in the header collection. 13 | /// 14 | public string Key { get; set; } 15 | 16 | /// 17 | /// The value stored under the key in the header collection. 18 | /// 19 | public string Value { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Helpers/ProcessUtil.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell 2 | { 3 | using System; 4 | using System.ComponentModel; 5 | using System.Management.Automation.Host; 6 | using System.Security.Principal; 7 | using System.ServiceProcess; 8 | 9 | /// 10 | /// Utility class for changing a windows service's status. 11 | /// 12 | public class ProcessUtil : CmdletHelperBase 13 | { 14 | public ProcessUtil(PSHost Host) : base(Host) 15 | { 16 | 17 | } 18 | 19 | public bool IsRunningWithElevatedPrivileges() 20 | { 21 | return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator); 22 | } 23 | 24 | /// 25 | /// Checks the status of the given controller, and if it isn't the requested state, 26 | /// performs the given action, and checks the state again. 27 | /// 28 | public void ChangeServiceStatus(ServiceController controller, ServiceControllerStatus status, Action changeStatus) 29 | { 30 | if (controller.Status == status) 31 | { 32 | WriteVerbose(controller.ServiceName + " status is good: " + Enum.GetName(typeof(ServiceControllerStatus), status)); 33 | return; 34 | } 35 | 36 | WriteWarning(controller.ServiceName + " status is NOT " + Enum.GetName(typeof(ServiceControllerStatus), status) + ". Changing status..."); 37 | 38 | try 39 | { 40 | changeStatus(); 41 | } 42 | catch (Win32Exception exception) 43 | { 44 | ThrowUnableToChangeStatus(controller.ServiceName, status, exception); 45 | } 46 | catch (InvalidOperationException exception) 47 | { 48 | ThrowUnableToChangeStatus(controller.ServiceName, status, exception); 49 | } 50 | 51 | var timeout = TimeSpan.FromSeconds(10); 52 | controller.WaitForStatus(status, timeout); 53 | if (controller.Status == status) 54 | WriteVerbose((controller.ServiceName + " status changed successfully.")); 55 | else 56 | ThrowUnableToChangeStatus(controller.ServiceName, status); 57 | } 58 | 59 | private void ThrowUnableToChangeStatus(string serviceName, ServiceControllerStatus status) 60 | { 61 | ThrowUnableToChangeStatus(serviceName, status, null); 62 | } 63 | 64 | private static void ThrowUnableToChangeStatus(string serviceName, ServiceControllerStatus status, Exception exception) 65 | { 66 | var message = "Unable to change " + serviceName + " status to " + Enum.GetName(typeof(ServiceControllerStatus), status); 67 | 68 | if (exception == null) 69 | { 70 | throw new InvalidOperationException(message); 71 | } 72 | 73 | throw new InvalidOperationException(message, exception); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Helpers/RegistryHelper.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell.Helpers 2 | { 3 | 4 | using System; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | using System.ComponentModel; 8 | using System.Runtime.InteropServices; 9 | using System.Text; 10 | using Microsoft.Win32; 11 | 12 | /// 13 | /// Registry Implementation that supports registry views for WOW32 and WOW64 for .Net 2 14 | /// 15 | internal class RegistryHelper 16 | { 17 | int WOWOption; 18 | IntPtr RootKey; 19 | 20 | const int KEY_QUERY_VALUE = 0x0001; 21 | const int KEY_SET_VALUE = 0x0002; 22 | const int KEY_CREATE_SUB_KEY = 0x0004; 23 | const int KEY_ENUMERATE_SUB_KEYS = 0x0008; 24 | const int KEY_NOTIFY = 0x0010; 25 | const int KEY_CREATE_LINK = 0x0020; 26 | const int KEY_READ = ((STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & (~SYNCHRONIZE)); 27 | const int KEY_WRITE = ((STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) & (~SYNCHRONIZE)); 28 | const int KEY_WOW64_64KEY = 0x0100; 29 | const int KEY_WOW64_32KEY = 0x0200; 30 | const int REG_OPTION_NON_VOLATILE = 0x0000; 31 | const int REG_OPTION_VOLATILE = 0x0001; 32 | const int REG_OPTION_CREATE_LINK = 0x0002; 33 | const int REG_OPTION_BACKUP_RESTORE = 0x0004; 34 | const int REG_NONE = 0; 35 | const int REG_SZ = 1; 36 | const int REG_EXPAND_SZ = 2; 37 | 38 | const int REG_BINARY = 3; 39 | const int REG_DWORD = 4; 40 | const int REG_DWORD_LITTLE_ENDIAN = 4; 41 | const int REG_DWORD_BIG_ENDIAN = 5; 42 | const int REG_LINK = 6; 43 | const int REG_MULTI_SZ = 7; 44 | const int REG_RESOURCE_LIST = 8; 45 | const int REG_FULL_RESOURCE_DESCRIPTOR = 9; 46 | const int REG_RESOURCE_REQUIREMENTS_LIST = 10; 47 | const int REG_QWORD = 11; 48 | const int READ_CONTROL = 0x00020000; 49 | const int SYNCHRONIZE = 0x00100000; 50 | 51 | const int STANDARD_RIGHTS_READ = READ_CONTROL; 52 | const int STANDARD_RIGHTS_WRITE = READ_CONTROL; 53 | 54 | const int SUCCESS = 0; 55 | const int FILE_NOT_FOUND = 2; 56 | const int ACCESS_DENIED = 5; 57 | const int INVALID_PARAMETER = 87; 58 | const int MORE_DATA = 234; 59 | const int NO_MORE_ENTRIES = 259; 60 | const int MARKED_FOR_DELETION = 1018; 61 | const int BUFFER_MAX_LENGTH = 2048; 62 | 63 | static readonly IntPtr HKEY_CURRENT_USER = new IntPtr(unchecked((int) 0x80000001)); 64 | static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(unchecked((int) 0x80000002)); 65 | 66 | const int MaxKeyLength = 255; 67 | const int MaxValueLength = 16383; 68 | 69 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 70 | static extern int RegOpenKeyEx(IntPtr hKey, string subKey, uint options, int sam, out IntPtr phkResult); 71 | 72 | [DllImport("advapi32.dll", CharSet = CharSet.Auto)] 73 | static extern int RegEnumKey(IntPtr keyBase, int index, StringBuilder nameBuffer, int bufferLength); 74 | 75 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 76 | static extern int RegCloseKey(IntPtr hKey); 77 | 78 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 79 | static extern int RegEnumValue(IntPtr hKey, int dwIndex, StringBuilder lpValueName, ref int lpcchValueName, int lpReserved, int lpType, int lpData, int lpcbData); 80 | 81 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false)] 82 | static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int[] lpReserved, ref int lpType, ref int lpData, ref int lpcbData); 83 | 84 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false)] 85 | static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int[] lpReserved, ref int lpType, ref long lpData, ref int lpcbData); 86 | 87 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false)] 88 | static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int[] lpReserved, ref int lpType, [Out] byte[] lpData, ref int lpcbData); 89 | 90 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false)] 91 | static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int[] lpReserved, ref int lpType, [Out] char[] lpData, ref int lpcbData); 92 | 93 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false)] 94 | static extern int RegSetValueEx(IntPtr hKey, string lpValueName, int reserved, RegistryValueKind dwType, byte[] lpData, int cbData); 95 | 96 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false)] 97 | static extern int RegSetValueEx(IntPtr hKey, string lpValueName, int reserved, RegistryValueKind dwType, ref int lpData, int cbData); 98 | 99 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false)] 100 | static extern int RegSetValueEx(IntPtr hKey, string lpValueName, int reserved, RegistryValueKind dwType, ref long lpData, int cbData); 101 | 102 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false)] 103 | static extern int RegSetValueEx(IntPtr hKey, string lpValueName, int reserved, RegistryValueKind dwType, string lpData, int cbData); 104 | 105 | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)] 106 | static extern int RegCreateKeyEx(IntPtr hKey, string lpSubKey, int reserved, string lpClass, int dwOptions, int samDesired, IntPtr lpSecurityAttributes, out IntPtr phkResult, out int lpdwDisposition); 107 | 108 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false)] 109 | static extern int RegDeleteKey(IntPtr hKey, string lpSubKey); 110 | 111 | [DllImport("advapi32.dll", CharSet = CharSet.Auto, BestFitMapping = false)] 112 | static extern int RegDeleteValue(IntPtr hKey, string lpValueName); 113 | 114 | public static RegistryHelper LocalMachine(RegistryView regView) 115 | { 116 | var helper = new RegistryHelper 117 | { 118 | RootKey = HKEY_LOCAL_MACHINE, 119 | WOWOption = (int) regView 120 | }; 121 | return helper; 122 | } 123 | 124 | public static RegistryHelper CurrentUser(RegistryView regView) 125 | { 126 | var helper = new RegistryHelper 127 | { 128 | RootKey = HKEY_CURRENT_USER, 129 | WOWOption = (int) regView 130 | }; 131 | return helper; 132 | } 133 | 134 | public string[] GetSubKeyNames(string subKeyName) 135 | { 136 | var regKeyHandle = IntPtr.Zero; 137 | var keyNames = new ArrayList(); 138 | try 139 | { 140 | if (RegOpenKeyEx(RootKey, subKeyName, 0, KEY_READ | WOWOption, out regKeyHandle) != 0) 141 | { 142 | throw new Exception("Failed to open registry key"); 143 | } 144 | var buffer = new StringBuilder(BUFFER_MAX_LENGTH); 145 | for (var index = 0;; index++) 146 | { 147 | var result = RegEnumKey(regKeyHandle, index, buffer, buffer.Capacity); 148 | 149 | if (result == SUCCESS) 150 | { 151 | keyNames.Add(buffer.ToString()); 152 | buffer.Length = 0; 153 | continue; 154 | } 155 | 156 | if (result == NO_MORE_ENTRIES) 157 | { 158 | break; 159 | } 160 | throw new Win32Exception(result); 161 | } 162 | return (string[]) keyNames.ToArray(typeof(string)); 163 | } 164 | finally 165 | { 166 | if (regKeyHandle != IntPtr.Zero) 167 | { 168 | RegCloseKey(regKeyHandle); 169 | } 170 | } 171 | } 172 | 173 | public string[] GetValueNames(string subKeyName) 174 | { 175 | var regKeyHandle = IntPtr.Zero; 176 | var keyNames = new ArrayList(); 177 | try 178 | { 179 | if (RegOpenKeyEx(RootKey, subKeyName, 0, KEY_READ | WOWOption, out regKeyHandle) != 0) 180 | { 181 | throw new Exception("Failed to open registry key"); 182 | } 183 | var buffer = new StringBuilder(256); 184 | 185 | for (var index = 0;; index++) 186 | { 187 | var bufferSize = 256; 188 | var result = RegEnumValue(regKeyHandle, index, buffer, ref bufferSize, 0, 0, 0, 0); 189 | if (result == SUCCESS) 190 | { 191 | keyNames.Add(buffer.ToString()); 192 | buffer.Capacity = 256; 193 | buffer.Length = 0; 194 | continue; 195 | } 196 | if (result == NO_MORE_ENTRIES) 197 | { 198 | break; 199 | } 200 | throw new Win32Exception(result); 201 | } 202 | return (string[]) keyNames.ToArray(typeof(string)); 203 | } 204 | finally 205 | { 206 | if (regKeyHandle != IntPtr.Zero) 207 | { 208 | RegCloseKey(regKeyHandle); 209 | } 210 | } 211 | } 212 | 213 | public object ReadValue(string subKeyName, string valueName, object defaultValue, bool doNotExpand) 214 | { 215 | var data = defaultValue; 216 | var type = 0; 217 | var datasize = 0; 218 | var regKeyHandle = IntPtr.Zero; 219 | try 220 | { 221 | if (RegOpenKeyEx(RootKey, subKeyName, 0, KEY_READ | WOWOption, out regKeyHandle) != 0) 222 | { 223 | throw new Exception("Failed to open registry key"); 224 | } 225 | var ret = RegQueryValueEx(regKeyHandle, valueName, null, ref type, (byte[]) null, ref datasize); 226 | if (ret != 0) 227 | { 228 | if (ret != MORE_DATA) 229 | { 230 | return data; //Error Return Default 231 | } 232 | } 233 | else 234 | { 235 | if (datasize < 0) 236 | { 237 | datasize = 0; 238 | } 239 | switch (type) 240 | { 241 | case REG_NONE: 242 | case REG_DWORD_BIG_ENDIAN: 243 | case REG_BINARY: 244 | { 245 | var blob = new byte[datasize]; 246 | RegQueryValueEx(regKeyHandle, valueName, null, ref type, blob, ref datasize); 247 | data = blob; 248 | } 249 | break; 250 | case REG_QWORD: 251 | { 252 | if (datasize > 8) 253 | { 254 | goto case REG_BINARY; 255 | } 256 | long blob = 0; 257 | RegQueryValueEx(regKeyHandle, valueName, null, ref type, ref blob, ref datasize); 258 | data = blob; 259 | } 260 | break; 261 | case REG_DWORD: 262 | { 263 | if (datasize > 4) 264 | { 265 | goto case REG_QWORD; 266 | } 267 | var blob = 0; 268 | RegQueryValueEx(regKeyHandle, valueName, null, ref type, ref blob, ref datasize); 269 | data = blob; 270 | } 271 | break; 272 | 273 | case REG_SZ: 274 | { 275 | var blob = new char[datasize/2]; 276 | RegQueryValueEx(regKeyHandle, valueName, null, ref type, blob, ref datasize); 277 | if (blob.Length > 0 && blob[blob.Length - 1] == (char) 0) 278 | { 279 | data = new string(blob, 0, blob.Length - 1); 280 | } 281 | else 282 | { 283 | data = new string(blob); 284 | } 285 | } 286 | break; 287 | case REG_EXPAND_SZ: 288 | { 289 | var blob = new char[datasize/2]; 290 | RegQueryValueEx(regKeyHandle, valueName, null, ref type, blob, ref datasize); 291 | if (blob.Length > 0 && blob[blob.Length - 1] == (char) 0) 292 | { 293 | data = new string(blob, 0, blob.Length - 1); 294 | } 295 | else 296 | { 297 | data = new string(blob); 298 | } 299 | if (!doNotExpand) 300 | data = Environment.ExpandEnvironmentVariables((string) data); 301 | } 302 | break; 303 | case REG_MULTI_SZ: 304 | { 305 | var blob = new char[datasize/2]; 306 | 307 | RegQueryValueEx(regKeyHandle, valueName, null, ref type, blob, ref datasize); 308 | 309 | // Ensure String is null terminated 310 | if (blob.Length > 0 && blob[blob.Length - 1] != (char) 0) 311 | { 312 | var newBlob = new char[checked(blob.Length + 1)]; 313 | for (var i = 0; i < blob.Length; i++) 314 | { 315 | newBlob[i] = blob[i]; 316 | } 317 | newBlob[newBlob.Length - 1] = (char) 0; 318 | blob = newBlob; 319 | blob[blob.Length - 1] = (char) 0; 320 | } 321 | 322 | IList strings = new List(); 323 | var cur = 0; 324 | var len = blob.Length; 325 | 326 | while (cur < len) 327 | { 328 | var nextNull = cur; 329 | while (nextNull < len && blob[nextNull] != (char) 0) 330 | { 331 | nextNull++; 332 | } 333 | 334 | if (nextNull < len) 335 | { 336 | if (nextNull - cur > 0) 337 | { 338 | strings.Add(new string(blob, cur, nextNull - cur)); 339 | } 340 | else 341 | { 342 | if (nextNull != len - 1) 343 | strings.Add(string.Empty); 344 | } 345 | } 346 | else 347 | { 348 | strings.Add(new string(blob, cur, len - cur)); 349 | } 350 | cur = nextNull + 1; 351 | } 352 | 353 | data = new string[strings.Count]; 354 | strings.CopyTo((string[]) data, 0); 355 | } 356 | break; 357 | } 358 | } 359 | return data; 360 | } 361 | finally 362 | { 363 | if (regKeyHandle != IntPtr.Zero) 364 | { 365 | RegCloseKey(regKeyHandle); 366 | } 367 | } 368 | } 369 | 370 | public bool ValueExists(string subKeyName, string valueName) 371 | { 372 | if (!KeyExists(subKeyName)) 373 | { 374 | return false; 375 | } 376 | var valueNames = GetValueNames(subKeyName); 377 | foreach (var x in valueNames) 378 | { 379 | if (string.Equals(x, valueName, StringComparison.OrdinalIgnoreCase)) 380 | { 381 | return true; 382 | } 383 | } 384 | return false; 385 | } 386 | 387 | public bool KeyExists(string subKeyName) 388 | { 389 | var regKeyHandle = IntPtr.Zero; 390 | try 391 | { 392 | 393 | if (RegOpenKeyEx(RootKey, subKeyName, 0, KEY_READ | WOWOption, out regKeyHandle) != 0) 394 | return false; 395 | if (regKeyHandle == IntPtr.Zero) 396 | return false; 397 | return true; 398 | } 399 | finally 400 | { 401 | if (regKeyHandle != IntPtr.Zero) 402 | { 403 | RegCloseKey(regKeyHandle); 404 | } 405 | } 406 | } 407 | 408 | public bool CreateSubkey(string subKeyName) 409 | { 410 | IntPtr regKeyHandle; 411 | 412 | int disposition; 413 | var status = RegCreateKeyEx(RootKey, subKeyName, 0, null, 0, KEY_READ | KEY_WRITE | WOWOption, IntPtr.Zero, out regKeyHandle, out disposition); 414 | 415 | return !(status != 0 | regKeyHandle == IntPtr.Zero); 416 | } 417 | 418 | public bool WriteValue(string subKeyName, string valueName, object value, RegistryValueKind valueKind) 419 | { 420 | if (value == null) 421 | { 422 | throw new ArgumentNullException("value", "value can't be null"); 423 | } 424 | if (valueName != null && valueName.Length > MaxValueLength) 425 | { 426 | throw new ArgumentException("value name is invalid"); 427 | } 428 | 429 | var regKeyHandle = IntPtr.Zero; 430 | try 431 | { 432 | 433 | int disposition; 434 | var status = RegCreateKeyEx(RootKey, subKeyName, 0, null, 0, KEY_READ | KEY_WRITE | WOWOption, IntPtr.Zero, out regKeyHandle, out disposition); 435 | 436 | if (status != 0) 437 | { 438 | throw new Win32Exception(); 439 | } 440 | 441 | switch (valueKind) 442 | { 443 | case RegistryValueKind.ExpandString: 444 | case RegistryValueKind.String: 445 | { 446 | var data = value.ToString(); 447 | return RegSetValueEx(regKeyHandle, valueName, 0, valueKind, data, checked((data.Length * 2) + 2)) == 0; 448 | } 449 | case RegistryValueKind.MultiString: 450 | { 451 | var stringsList = (string[]) value; 452 | var data = string.Join("\0", stringsList) + "\0\0"; 453 | return RegSetValueEx(regKeyHandle, valueName, 0, valueKind, data, checked((data.Length * 2) + 2)) == 0; 454 | } 455 | case RegistryValueKind.Binary: 456 | { 457 | var dataBytes = (byte[]) value; 458 | return RegSetValueEx(regKeyHandle, valueName, 0, RegistryValueKind.Binary, dataBytes, dataBytes.Length) == 0; 459 | } 460 | case RegistryValueKind.DWord: 461 | { 462 | var data = Convert.ToInt32(value, System.Globalization.CultureInfo.InvariantCulture); 463 | return RegSetValueEx(regKeyHandle, valueName, 0, RegistryValueKind.DWord, ref data, 4) == 0; 464 | } 465 | case RegistryValueKind.QWord: 466 | { 467 | var data = Convert.ToInt64(value, System.Globalization.CultureInfo.InvariantCulture); 468 | return RegSetValueEx(regKeyHandle, valueName, 0, RegistryValueKind.QWord, ref data, 8) == 0; 469 | } 470 | default: 471 | throw new NotImplementedException($"RegistryKind {valueKind} not supported"); 472 | } 473 | 474 | } 475 | catch (Exception ex) 476 | { 477 | throw new Exception("Failed to write value", ex); 478 | } 479 | finally 480 | { 481 | if (regKeyHandle != IntPtr.Zero) 482 | { 483 | RegCloseKey(regKeyHandle); 484 | } 485 | } 486 | } 487 | 488 | public bool DeleteKeyTree(string subKeyName) 489 | { 490 | if (!KeyExists(subKeyName)) 491 | { 492 | return true; 493 | } 494 | 495 | var keysToRemoveList = new List 496 | { 497 | subKeyName 498 | }; 499 | 500 | RecurseKeys(subKeyName, ref keysToRemoveList); 501 | 502 | //Reverse the order of the list so children are removed prior to parents 503 | var keysToRemove = keysToRemoveList.ToArray(); 504 | 505 | Array.Reverse(keysToRemove); 506 | foreach (var key in keysToRemove) 507 | { 508 | if (RegDeleteKey(RootKey, key) != 0) 509 | { 510 | return false; 511 | } 512 | } 513 | return true; 514 | } 515 | 516 | void RecurseKeys(string key, ref List keysList) 517 | { 518 | foreach (var subKeyName in GetSubKeyNames(key)) 519 | { 520 | var fullPath = $@"{key}\{subKeyName}"; 521 | keysList.Add(fullPath); 522 | RecurseKeys(fullPath, ref keysList); 523 | } 524 | } 525 | 526 | public bool DeleteValue(string subKeyName, string valueName) 527 | { 528 | if (!KeyExists(subKeyName)) 529 | { 530 | return true; 531 | } 532 | 533 | var regKeyHandle = IntPtr.Zero; 534 | if (!ValueExists(subKeyName, valueName)) 535 | { 536 | return true; 537 | } 538 | try 539 | { 540 | int disposition; 541 | var status = RegCreateKeyEx(RootKey, subKeyName, 0, null, 0, KEY_READ | KEY_WRITE | WOWOption, IntPtr.Zero, out regKeyHandle, out disposition); 542 | if (status != 0 || RegDeleteValue(regKeyHandle, valueName) != 0) 543 | { 544 | throw new Win32Exception(); 545 | } 546 | return true; 547 | } 548 | catch (Exception) 549 | { 550 | return false; 551 | } 552 | finally 553 | { 554 | if (regKeyHandle != IntPtr.Zero) 555 | { 556 | RegCloseKey(regKeyHandle); 557 | } 558 | } 559 | } 560 | 561 | public RegistryValueKind GetRegistryValueKind(string subKeyName, string valueName) 562 | { 563 | var regKeyHandle = IntPtr.Zero; 564 | try 565 | { 566 | if (RegOpenKeyEx(RootKey, subKeyName, 0, KEY_READ | WOWOption, out regKeyHandle) != 0) 567 | { 568 | throw new Exception("Failed to open registry key"); 569 | } 570 | var type = 0; 571 | var datasize = 0; 572 | var ret = RegQueryValueEx(regKeyHandle, valueName, null, ref type, (byte[]) null, ref datasize); 573 | if (ret != 0) 574 | throw new Win32Exception(ret); 575 | if (!Enum.IsDefined(typeof(RegistryValueKind), type)) 576 | { 577 | return RegistryValueKind.Unknown; 578 | } 579 | return (RegistryValueKind) type; 580 | } 581 | finally 582 | { 583 | if (regKeyHandle != IntPtr.Zero) 584 | { 585 | RegCloseKey(regKeyHandle); 586 | } 587 | } 588 | } 589 | } 590 | } 591 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Helpers/RegistryView.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell.Helpers 2 | { 3 | /// 4 | /// Registry Views for .Net 2 5 | /// See RegistryHelper.cs 6 | /// 7 | internal enum RegistryView 8 | { 9 | Default = 0, 10 | Registry64 = 0x0100, 11 | Registry32 = 0x0200, 12 | } 13 | } -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Helpers/StreamExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell.Helpers 2 | { 3 | using System.IO; 4 | 5 | internal static class StreamsExtensions 6 | { 7 | const int bufferSize = 81920; 8 | 9 | //Replacement for .Net 4 CopyTo - This doesn't exist in .Net 2 10 | public static void CopyTo(this Stream source, Stream destination) 11 | { 12 | var buffer = new byte[bufferSize]; 13 | int read; 14 | while ((read = source.Read(buffer, 0, buffer.Length)) != 0) 15 | destination.Write(buffer, 0, read); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Helpers/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NServiceBus.PowerShell.Helpers 4 | { 5 | internal static class StringExtensions 6 | { 7 | /// 8 | /// Mimics the IsNullOrWhiteSpace method 9 | /// 10 | public static bool IsNullOrWhiteSpace(string value) 11 | { 12 | if (value == null) return true; 13 | 14 | for (var i = 0; i < value.Length; i++) 15 | { 16 | if (!char.IsWhiteSpace(value[i])) 17 | return false; 18 | } 19 | return true; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/InternalsVisibleTo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("NServiceBus.PowerShell.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100dde965e6172e019ac82c2639ffe494dd2e7dd16347c34762a05732b492e110f2e4e2e1b5ef2d85c848ccfb671ee20a47c8d1376276708dc30a90ff1121b647ba3b7259a6bc383b2034938ef0e275b58b920375ac605076178123693c6c4f1331661a62eba28c249386855637780e3ff5f23a6d854700eaa6803ef48907513b92")] -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/Msmq/MsmqSetup.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable CommentTypo 2 | namespace NServiceBus.PowerShell 3 | { 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.IO; 8 | using System.Management.Automation.Host; 9 | using System.Runtime.InteropServices; 10 | using System.ServiceProcess; 11 | using System.Text; 12 | using Helpers; 13 | 14 | /// 15 | /// Utility class for starting and installing MSMQ. 16 | /// 17 | public class MsmqSetup : CmdletHelperBase 18 | { 19 | 20 | public MsmqSetup() 21 | { 22 | 23 | } 24 | 25 | public MsmqSetup(PSHost Host) : base(Host) 26 | { 27 | 28 | } 29 | 30 | /// 31 | /// Checks that MSMQ is installed, configured correctly, and started, and if not takes the necessary corrective actions to make it so. 32 | /// 33 | public bool StartMsmqIfNecessary() 34 | { 35 | var processUtil = new ProcessUtil(Host); 36 | 37 | if (!InstallMsmqIfNecessary()) 38 | { 39 | return false; 40 | } 41 | 42 | try 43 | { 44 | using (var controller = new ServiceController("MSMQ")) 45 | { 46 | if (IsStopped(controller)) 47 | { 48 | processUtil.ChangeServiceStatus(controller, ServiceControllerStatus.Running, controller.Start); 49 | } 50 | } 51 | } 52 | catch (InvalidOperationException) 53 | { 54 | WriteWarning("MSMQ windows service not found! You may need to reboot after MSMQ has been installed."); 55 | return false; 56 | } 57 | 58 | return true; 59 | } 60 | 61 | static bool IsStopped(ServiceController controller) 62 | { 63 | return controller.Status == ServiceControllerStatus.Stopped || controller.Status == ServiceControllerStatus.StopPending; 64 | } 65 | 66 | internal bool IsMsmqInstalled() 67 | { 68 | var dll = LoadLibraryW("Mqrt.dll"); 69 | return (dll != IntPtr.Zero); 70 | } 71 | 72 | /// 73 | /// Determines if the msmq installation on the current machine is ok 74 | /// 75 | public bool IsInstallationGood() 76 | { 77 | const string subkey = @"SOFTWARE\Microsoft\MSMQ\Setup"; 78 | var regView = EnvironmentHelper.Is64BitOperatingSystem ? RegistryView.Registry64 : RegistryView.Default; 79 | var hklm = RegistryHelper.LocalMachine(regView); 80 | if (!hklm.KeyExists(subkey)) 81 | { 82 | return false; 83 | } 84 | 85 | return HasOnlyNeededComponents(hklm.GetValueNames(subkey)); 86 | } 87 | 88 | bool InstallMsmqIfNecessary() 89 | { 90 | WriteVerbose("Checking if MSMQ is installed."); 91 | 92 | var os = GetOperatingSystem(); 93 | 94 | if (IsMsmqInstalled()) 95 | { 96 | WriteVerbose("MSMQ is installed."); 97 | WriteVerbose("Checking that only needed components are active."); 98 | 99 | if (IsInstallationGood()) 100 | { 101 | WriteVerbose("Installation is good."); 102 | return true; 103 | } 104 | 105 | WriteWarning("Installation isn't good. Make sure you remove the following components: {0} and also {1}", string.Join(", ", UndesirableMsmqComponentsXp.ToArray()), string.Join(", ", UndesirableMsmqComponentsV4.ToArray())); 106 | return false; 107 | } 108 | 109 | WriteVerbose("MSMQ is not installed. Going to install."); 110 | 111 | switch (os) 112 | { 113 | case OperatingSystemEnum.XpOrServer2003: 114 | InstallMsmqOnXpOrServer2003(); 115 | break; 116 | 117 | case OperatingSystemEnum.Vista: 118 | RunExe(OcSetup, OcSetupVistaInstallCommand); 119 | break; 120 | 121 | case OperatingSystemEnum.Server2008: 122 | RunExe(OcSetup, OcSetupInstallCommand); 123 | break; 124 | 125 | case OperatingSystemEnum.Windows7: 126 | RunExe(dismPath, "/Online /NoRestart /English /Enable-Feature /FeatureName:MSMQ-Container /FeatureName:MSMQ-Server"); 127 | break; 128 | case OperatingSystemEnum.Windows8: 129 | case OperatingSystemEnum.Windows10: 130 | case OperatingSystemEnum.Server2012: 131 | RunExe(dismPath, "/Online /NoRestart /English /Enable-Feature /all /FeatureName:MSMQ-Server"); 132 | break; 133 | 134 | default: 135 | WriteWarning("OS not supported."); 136 | return false; 137 | } 138 | 139 | WriteVerbose("Installation of MSMQ successful."); 140 | 141 | return true; 142 | } 143 | 144 | [DllImport("kernel32.dll", SetLastError = true)] 145 | public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr); 146 | 147 | [DllImport("kernel32.dll", SetLastError = true)] 148 | public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr); 149 | 150 | public void RunExe(string filename, string args) 151 | { 152 | var startInfo = new ProcessStartInfo(filename, args) 153 | { 154 | CreateNoWindow = true, 155 | UseShellExecute = false, 156 | RedirectStandardOutput = true, 157 | RedirectStandardError = true, 158 | WorkingDirectory = Path.GetTempPath() 159 | }; 160 | 161 | WriteVerbose("Executing {0} {1}", startInfo.FileName, startInfo.Arguments); 162 | 163 | var ptr = new IntPtr(); 164 | var fileSystemRedirectionDisabled = false; 165 | 166 | if (EnvironmentHelper.Is64BitOperatingSystem) 167 | { 168 | fileSystemRedirectionDisabled = Wow64DisableWow64FsRedirection(ref ptr); 169 | } 170 | 171 | try 172 | { 173 | using (var process = new Process()) 174 | { 175 | var output = new StringBuilder(); 176 | var error = new StringBuilder(); 177 | 178 | process.StartInfo = startInfo; 179 | 180 | process.OutputDataReceived += (sender, e) => 181 | { 182 | if (e.Data != null) 183 | { 184 | output.AppendLine(e.Data); 185 | } 186 | }; 187 | process.ErrorDataReceived += (sender, e) => 188 | { 189 | if (e.Data != null) 190 | { 191 | error.AppendLine(e.Data); 192 | } 193 | }; 194 | 195 | process.Start(); 196 | process.BeginOutputReadLine(); 197 | process.BeginErrorReadLine(); 198 | 199 | process.WaitForExit(); 200 | 201 | WriteLine(output.ToString()); 202 | WriteLine(error.ToString()); 203 | } 204 | } 205 | finally 206 | { 207 | if (fileSystemRedirectionDisabled) 208 | { 209 | Wow64RevertWow64FsRedirection(ptr); 210 | } 211 | } 212 | } 213 | 214 | void InstallMsmqOnXpOrServer2003() 215 | { 216 | var p = Path.GetTempFileName(); 217 | 218 | WriteVerbose("Creating installation instructions file."); 219 | 220 | using (var sw = File.CreateText(p)) 221 | { 222 | sw.WriteLine("[Version]"); 223 | sw.WriteLine("Signature = \"$Windows NT$\""); 224 | sw.WriteLine(); 225 | sw.WriteLine("[Global]"); 226 | sw.WriteLine("FreshMode = Custom"); 227 | sw.WriteLine("MaintenanceMode = RemoveAll"); 228 | sw.WriteLine("UpgradeMode = UpgradeOnly"); 229 | sw.WriteLine(); 230 | sw.WriteLine("[Components]"); 231 | 232 | foreach (var s in RequiredMsmqComponentsXp) 233 | sw.WriteLine(s + " = ON"); 234 | 235 | foreach (var s in UndesirableMsmqComponentsXp) 236 | sw.WriteLine(s + " = OFF"); 237 | 238 | sw.Flush(); 239 | } 240 | 241 | WriteVerbose("Installation instructions file created."); 242 | WriteVerbose("Invoking MSMQ installation."); 243 | 244 | RunExe("sysocmgr", "/i:sysoc.inf /x /q /w /u:%temp%\\" + Path.GetFileName(p)); 245 | } 246 | 247 | // Based on http://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx 248 | static OperatingSystemEnum GetOperatingSystem() 249 | { 250 | var osVersionInfoEx = new OSVersionInfoEx 251 | { 252 | OSVersionInfoSize = (uint)Marshal.SizeOf(typeof(OSVersionInfoEx)) 253 | }; 254 | 255 | GetVersionEx(osVersionInfoEx); 256 | 257 | switch (Environment.OSVersion.Version.Major) 258 | { 259 | case 10: 260 | return OperatingSystemEnum.Windows10; 261 | 262 | case 6: 263 | switch (Environment.OSVersion.Version.Minor) 264 | { 265 | case 0: 266 | 267 | if (osVersionInfoEx.ProductType == VER_NT_WORKSTATION) 268 | { 269 | return OperatingSystemEnum.Vista; 270 | } 271 | 272 | return OperatingSystemEnum.Server2008; 273 | 274 | case 1: 275 | if (osVersionInfoEx.ProductType == VER_NT_WORKSTATION) 276 | { 277 | return OperatingSystemEnum.Windows7; 278 | } 279 | 280 | return OperatingSystemEnum.Server2008; 281 | 282 | case 2: 283 | case 3: 284 | if (osVersionInfoEx.ProductType == VER_NT_WORKSTATION) 285 | { 286 | return OperatingSystemEnum.Windows8; 287 | } 288 | 289 | return OperatingSystemEnum.Server2012; 290 | } 291 | break; 292 | 293 | case 5: 294 | return OperatingSystemEnum.XpOrServer2003; 295 | } 296 | 297 | return OperatingSystemEnum.Unsupported; 298 | } 299 | 300 | bool HasOnlyNeededComponents(IEnumerable installedComponents) 301 | { 302 | var needed = new List(RequiredMsmqComponentsXp); 303 | 304 | foreach (var i in installedComponents) 305 | { 306 | if (UndesirableMsmqComponentsXp.Contains(i)) 307 | { 308 | WriteWarning("Undesirable MSMQ component installed: " + i); 309 | return false; 310 | } 311 | 312 | if (UndesirableMsmqComponentsV4.Contains(i)) 313 | { 314 | WriteWarning("Undesirable MSMQ component installed: " + i); 315 | return false; 316 | } 317 | 318 | needed.Remove(i); 319 | } 320 | 321 | if (needed.Count == 0) 322 | return true; 323 | 324 | return false; 325 | } 326 | 327 | // Return Type: HMODULE->HINSTANCE->HINSTANCE__* 328 | // lpLibFileName: LPCWSTR->WCHAR* 329 | [DllImport("kernel32.dll", EntryPoint = "LoadLibraryW")] 330 | static extern IntPtr LoadLibraryW([In][MarshalAs(UnmanagedType.LPWStr)] string lpLibFileName); 331 | 332 | 333 | [DllImport("Kernel32", CharSet = CharSet.Auto)] 334 | static extern bool GetVersionEx([Out][In] OSVersionInfo versionInformation); 335 | 336 | 337 | // ReSharper disable UnusedField.Compiler 338 | // ReSharper disable NotAccessedField.Local 339 | // ReSharper disable UnassignedField.Compiler 340 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 341 | internal class OSVersionInfoEx : OSVersionInfo 342 | { 343 | public ushort ServicePackMajor; 344 | public ushort ServicePackMinor; 345 | public ushort SuiteMask; 346 | public byte ProductType; 347 | public byte Reserved; 348 | } 349 | 350 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 351 | internal class OSVersionInfo 352 | { 353 | // ReSharper disable once NotAccessedField.Global 354 | public uint OSVersionInfoSize = 355 | (uint)Marshal.SizeOf(typeof(OSVersionInfo)); 356 | 357 | public uint MajorVersion = 0; 358 | public uint MinorVersion = 0; 359 | public uint BuildNumber = 0; 360 | public uint PlatformId = 0; 361 | // Attribute used to indicate marshalling for String field 362 | [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] 363 | public string CSDVersion = null; 364 | } 365 | 366 | // ReSharper restore UnusedField.Compiler 367 | // ReSharper restore NotAccessedField.Local 368 | // ReSharper restore UnassignedField.Compiler 369 | const byte VER_NT_WORKSTATION = 1; 370 | 371 | static List RequiredMsmqComponentsXp = new List(new[] 372 | { 373 | "msmq_Core", 374 | "msmq_LocalStorage" 375 | }); 376 | 377 | static List UndesirableMsmqComponentsXp = new List(new[] 378 | { 379 | "msmq_ADIntegrated", 380 | "msmq_TriggersService", 381 | "msmq_HTTPSupport", 382 | "msmq_RoutingSupport", 383 | "msmq_MQDSService" 384 | }); 385 | 386 | static List UndesirableMsmqComponentsV4 = new List(new[] 387 | { 388 | "msmq_DCOMProxy", 389 | "msmq_MQDSServiceInstalled", 390 | "msmq_MulticastInstalled", 391 | "msmq_RoutingInstalled", 392 | "msmq_TriggersInstalled" 393 | }); 394 | 395 | internal enum OperatingSystemEnum 396 | { 397 | Unsupported, 398 | XpOrServer2003, 399 | Vista, 400 | Server2008, 401 | Windows7, 402 | Windows8, 403 | Server2012, 404 | Windows10 405 | } 406 | 407 | const string OcSetup = "OCSETUP"; 408 | static string dismPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "dism.exe"); 409 | const string OcSetupInstallCommand = "MSMQ-Server /passive"; 410 | const string OcSetupVistaInstallCommand = "MSMQ-Container;MSMQ-Server /passive"; 411 | } 412 | } 413 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/NServiceBus.PowerShell.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net452 5 | true 6 | ..\NServiceBus.snk 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/NServiceBus.PowerShell.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | False -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/NServiceBus.PowerShell.dll-help.xml: -------------------------------------------------------------------------------- 1 |  2 | 8 | 9 | 10 | 11 | Get-NServiceBusLocalMachineSettings 12 | Get 13 | NServiceBusLocalMachineSettings 14 | 15 | Shows the default Error and Audit queues. 16 | 17 | 18 | 19 | Reads the registry settings for the default audit and error queues. These settings can be found in the registry "HKEY_LOCAL_MACHINE\SOFTWARE\ParticularSoftware\ServiceBus". On 64 bit operating system the setting can also be set in the 32 bit registry. This cmdlet will list both 64-bit and 32-bit settings. 20 | To add these properties use Set-NServiceBusLocalMachineSettings 21 | 22 | 23 | 24 | Get-NServiceBusLocalMachineSettings 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 | This cmdlet requires elevated privileges. 58 | 59 | 60 | 61 | 62 | 63 | 64 | Set-NServiceBusLocalMachineSettings 65 | 66 | 67 | 68 | Clear-NServiceBusLocalMachineSettings 69 | 70 | 71 | 72 | http://docs.particular.net 73 | 74 | 75 | 76 | 77 | 78 | 79 | Install-NServiceBusDTC 80 | Install 81 | NServiceBusDTC 82 | 83 | Configures DTC on the machine to work with NServiceBus 84 | 85 | 86 | 87 | This cmdlet will configure and attempt to start the Microsoft Distributed Transaction Coordinator service on this machine. To configure MSDTC with NServiceBus the cmdlet sets the following values under the "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\Security" registry key: 88 | NetworkDtcAccess : 1 (DWORD) 89 | NetworkDtcAccessOutbound : 1 (DWORD) 90 | NetworkDtcAccessTransactions: 1 (DWORD) 91 | XaTransactions : 1 (DWORD) 92 | If the optional PortRange parameter is supplied, then this value will be used for the DCOM Configuration. The format should be two numbers separated by a dash. (e.g. "5000-6000"). Specifically, the cmdlet will set the following values under the 93 | "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Rpc\Internet" registry key: 94 | Ports : [Based on value of PortRange parameter] (Multi-String Value) 95 | PortsInternetAvailable : "Y" (String Value) 96 | UseInternetPorts : "Y" (String Value) 97 | 98 | 99 | 100 | Install-NServiceBusDTC 101 | 102 | WhatIf 103 | 104 | 105 | 106 | SwitchParameter 107 | 108 | 109 | Confirm 110 | 111 | 112 | 113 | SwitchParameter 114 | 115 | 116 | 117 | 118 | 119 | PortRange 120 | 121 | 122 | 123 | String 124 | 125 | String 126 | 127 | 128 | 129 | 130 | 131 | WhatIf 132 | 133 | 134 | 135 | SwitchParameter 136 | 137 | SwitchParameter 138 | 139 | 140 | 141 | 142 | 143 | Confirm 144 | 145 | 146 | 147 | SwitchParameter 148 | 149 | SwitchParameter 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 | This cmdlet requires elevated privileges. 185 | 186 | 187 | 188 | 189 | 190 | 191 | Test-NServiceBusDTCInstallation 192 | 193 | 194 | 195 | http://docs.particular.net 196 | 197 | 198 | 199 | 200 | 201 | 202 | Install-NServiceBusMSMQ 203 | Install 204 | NServiceBusMSMQ 205 | 206 | Configures MSMQ on the machine to work with NServiceBus 207 | 208 | 209 | 210 | This cmdlet will configure and attempt install and configuration the MSMQ service on this machine. The cmdlet uses either OCSetup.exe or DISM.exe command to install the required Windows Feature depending on the version of Windows installed. 211 | If a Windows Feature installation is installed a reboot may be required to complete the install. 212 | 213 | 214 | 215 | Install-NServiceBusMSMQ 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | This cmdlet requires elevated privileges. 250 | 251 | 252 | 253 | 254 | 255 | 256 | Test-NServiceBusMSMQInstallation 257 | 258 | 259 | 260 | http://docs.particular.net 261 | 262 | 263 | 264 | 265 | 266 | 267 | Install-NServiceBusPerformanceCounters 268 | Install 269 | NServiceBusPerformanceCounters 270 | 271 | Adds NServiceBus performance counters on this machine. 272 | 273 | 274 | 275 | This cmdlet adds the "NServiceBus statistics" Performance Monitor category. 276 | Underneath this category the following counter are added: 277 | - Critical Time 278 | - SLA violation countdown 279 | - # of msgs successfully processed / sec 280 | - # of msgs pulled from the input queue /sec 281 | - # of msgs failures / sec 282 | Use the Test-NServiceBusPerformanceCountersInstallation cmdlet to verify the counters exist. 283 | 284 | 285 | 286 | 287 | Install-NServiceBusPerformanceCounters 288 | 289 | Force 290 | 291 | 292 | 293 | SwitchParameter 294 | 295 | 296 | 297 | 298 | 299 | Force 300 | 301 | 302 | 303 | SwitchParameter 304 | 305 | SwitchParameter 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | This cmdlet requires elevated privileges. 341 | 342 | 343 | 344 | 345 | 346 | 347 | Test-NServiceBusPerformanceCountersInstallation 348 | 349 | 350 | 351 | Uninstall-NServiceBusPerformanceCounters 352 | 353 | 354 | 355 | http://docs.particular.net 356 | 357 | 358 | 359 | 360 | 361 | 362 | Remove-NServiceBusMSMQWorker 363 | Remove 364 | NServiceBusMSMQWorker 365 | 366 | Sends a disconnect message to the distributor to remove a worker. 367 | 368 | 369 | 370 | This cmdlet can be used to sent a disconnect message to the Distributor control queue. 371 | When the Distributor processes it, the Worker with the address specified in the message is set to "disconnected". 372 | 373 | 374 | 375 | Remove-NServiceBusMSMQWorker 376 | 377 | WorkerAddress 378 | 379 | 380 | 381 | String 382 | 383 | 384 | DistributorAddress 385 | 386 | 387 | 388 | String 389 | 390 | 391 | TransactionalDistributorQueue 392 | 393 | 394 | 395 | Boolean 396 | 397 | 398 | 399 | 400 | 401 | WorkerAddress 402 | 403 | 404 | 405 | String 406 | 407 | String 408 | 409 | 410 | 411 | 412 | 413 | DistributorAddress 414 | 415 | 416 | 417 | String 418 | 419 | String 420 | 421 | 422 | 423 | 424 | 425 | TransactionalDistributorQueue 426 | 427 | 428 | 429 | Boolean 430 | 431 | Boolean 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | This cmdlet requires elevated privileges. 467 | 468 | 469 | 470 | 471 | 472 | 473 | http://docs.particular.net 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | Set-NServiceBusLocalMachineSettings 485 | Set 486 | NServiceBusLocalMachineSettings 487 | 488 | Sets the default Error and Audit queues. 489 | 490 | 491 | 492 | Sets the registry settings for the default audit and error queues. These settings can be found in the registry under "HKEY_LOCAL_MACHINE\SOFTWARE\ParticularSoftware\ServiceBus". On 64 bit operating system the settings are applied to both the 32-bit and 64-bit registry. 493 | 494 | 495 | 496 | Set-NServiceBusLocalMachineSettings 497 | 498 | ErrorQueue 499 | 500 | 501 | 502 | String 503 | 504 | 505 | AuditQueue 506 | 507 | 508 | 509 | String 510 | 511 | 512 | 513 | 514 | 515 | ErrorQueue 516 | 517 | 518 | 519 | String 520 | 521 | String 522 | 523 | 524 | 525 | 526 | 527 | AuditQueue 528 | 529 | 530 | 531 | String 532 | 533 | String 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | This cmdlet requires elevated privileges. 569 | 570 | 571 | 572 | 573 | 574 | 575 | Get-NServiceBusLocalMachineSettings 576 | 577 | 578 | 579 | Clear-NServiceBusLocalMachineSettings 580 | 581 | 582 | 583 | http://docs.particular.net 584 | 585 | 586 | 587 | 588 | 589 | 590 | Test-NServiceBusDTCInstallation 591 | Test 592 | NServiceBusDTCInstallation 593 | 594 | Test the configuration of the DTC service to ensure it has the appropriate setting to work with NServiceBus 595 | 596 | 597 | 598 | This cmdlet will check the Microsoft Distributed Transaction Co-ordinator service on this machine is setup for use with NServiceBus. Specifically it checks the following values under the "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\Security" registry key are set as follows: 599 | NetworkDtcAccess : 1 (DWORD) 600 | NetworkDtcAccessOutbound : 1 (DWORD) 601 | NetworkDtcAccessTransactions: 1 (DWORD) 602 | XaTransactions : 1 (DWORD) 603 | These settings can be set by using the Install-NServiceBusDTC cmdlet 604 | 605 | 606 | 607 | Test-NServiceBusDTCInstallation 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | This cmdlet requires elevated privileges. 641 | 642 | 643 | 644 | 645 | 646 | 647 | Install-NServiceBusDTC 648 | 649 | 650 | 651 | http://docs.particular.net 652 | 653 | 654 | 655 | 656 | 657 | 658 | Test-NServiceBusMSMQInstallation 659 | Test 660 | NServiceBusMSMQInstallation 661 | 662 | Validates MSMQ is correctly installed on the machine 663 | 664 | 665 | 666 | This cmdlet validates MSMQ is installed on the machine and the correct MSMQ sub features are installed. The cmdlet will also check that the service is started. 667 | 668 | 669 | 670 | Test-NServiceBusMSMQInstallation 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | This cmdlet requires elevated privileges. 704 | 705 | 706 | 707 | 708 | 709 | 710 | Install-NServiceBusMSMQ 711 | 712 | 713 | 714 | http://docs.particular.net 715 | 716 | 717 | 718 | 719 | 720 | 721 | Test-NServiceBusPerformanceCountersInstallation 722 | Test 723 | NServiceBusPerformanceCountersInstallation 724 | 725 | Validates that NServiceBus performance counters are correctly installed on the machine. 726 | 727 | 728 | 729 | This cmdlet validates that NServiceBus performance counters are correctly installed on the machine. Refer to Install-NserviceBusPerformanceCounters for more details regarding the NServiceBus performance counters. 730 | 731 | 732 | 733 | Test-NServiceBusPerformanceCountersInstallation 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | This cmdlet requires elevated privileges. 767 | 768 | 769 | 770 | 771 | 772 | 773 | Install-NServiceBusPerformanceCounters 774 | 775 | 776 | 777 | Uninstall-NServiceBusPerformanceCounters 778 | 779 | 780 | 781 | http://docs.particular.net 782 | 783 | 784 | 785 | 786 | 787 | 788 | Uninstall-NServiceBusPerformanceCounters 789 | Uninstall 790 | NServiceBusPerformanceCounters 791 | 792 | Removes the NServiceBus performance counters from this machine. 793 | 794 | 795 | 796 | 797 | This cmdlet removes the NServiceBus performance if they are installed on this machine. Refer to Install-NserviceBusPerformanceCounters for more details regarding the NServiceBus performance counters. 798 | 799 | 800 | 801 | 802 | Uninstall-NServiceBusPerformanceCounters 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | This cmdlet requires elevated privileges 837 | Refer to https://docs.particular.net for more information 838 | 839 | 840 | 841 | 842 | 843 | 844 | Install-NServiceBusPerformanceCounters 845 | 846 | 847 | 848 | Test-NServiceBusPerformanceCountersInstallation 849 | 850 | 851 | 852 | http://docs.particular.net 853 | 854 | 855 | 856 | 857 | 858 | 859 | Clear-NServiceBusLocalMachineSettings 860 | Clear 861 | NServiceBusLocalMachineSettings 862 | 863 | Removes the default Error and Audit queues settings. 864 | 865 | 866 | 867 | Removes the registry settings for the default audit and error queues. These settings can be found in the registry "HKEY_LOCAL_MACHINE\SOFTWARE\ParticularSoftware\ServiceBus". On 64 bit operating system the setting is removed in both the 32 bit registry and 64 bit registry. 868 | 869 | 870 | 871 | Clear-NServiceBusLocalMachineSettings 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | This cmdlet requires elevated privileges. 905 | 906 | 907 | 908 | 909 | 910 | 911 | Get-NServiceBusLocalMachineSettings 912 | 913 | 914 | 915 | Set-NServiceBusLocalMachineSettings 916 | 917 | 918 | 919 | http://docs.particular.net 920 | 921 | 922 | 923 | 924 | 925 | 926 | Install-NServiceBusPlatformLicense 927 | Install 928 | NServiceBusPlatformLicense 929 | 930 | Imports the Particular Platform License into the registry 931 | 932 | 933 | 934 | Imports the the Particular Platform License into the registry. For 64-bit operating systems the license is written to both the 32-bit and 64-bit registry. Provide either LicenseFile or LicenseString. 935 | 936 | 937 | 938 | Install-NServiceBusPlatformLicense 939 | 940 | LicenseFile 941 | 942 | 943 | 944 | String 945 | 946 | 947 | 948 | 949 | LicenseString 950 | 951 | 952 | 953 | String 954 | 955 | 956 | 957 | 958 | 959 | LicenseFile 960 | 961 | 962 | 963 | String 964 | 965 | String 966 | 967 | 968 | 969 | 970 | 971 | LicenseString 972 | 973 | 974 | 975 | String 976 | 977 | String 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | This cmdlet requires elevated privileges. 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/NServiceBus.PowerShell.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | GUID = 'ABFF92C4-A8BA-4CAA-A40D-8C97F3B28934' 3 | Author = 'Particular Software' 4 | Description = 'NServiceBus PowerShell' 5 | ModuleVersion = '{{Version}}' 6 | NestedModules = 'NServiceBus.PowerShell.dll' 7 | CLRVersion = '4.0' 8 | DotNetFrameworkVersion = '4.5.2' 9 | CompanyName = 'Particular Software' 10 | Copyright = '(c) 2020 NServiceBus Ltd. All rights reserved.' 11 | FunctionsToExport='*' 12 | CmdletsToExport = '*' 13 | VariablesToExport = '*' 14 | AliasesToExport = '*' 15 | FormatsToProcess = @( 16 | '.\Formats\NServiceBus.Powershell.Cmdlets.InstallationResult.format.ps1xml', 17 | '.\Formats\NServiceBus.Powershell.Cmdlets.MachineSettingsResult.format.ps1xml' 18 | ) 19 | } 20 | -------------------------------------------------------------------------------- /src/NServiceBus.PowerShell/PerformanceCounters/PerformanceCounterSetup.cs: -------------------------------------------------------------------------------- 1 | namespace NServiceBus.PowerShell 2 | { 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Management.Automation.Host; 6 | 7 | public class PerformanceCounterSetup : CmdletHelperBase 8 | { 9 | 10 | public PerformanceCounterSetup() 11 | { 12 | } 13 | 14 | public PerformanceCounterSetup(PSHost Host) : base(Host) 15 | { 16 | } 17 | 18 | const string categoryName = "NServiceBus"; 19 | 20 | public bool CheckCounters() 21 | { 22 | return PerformanceCounterCategory.Exists(categoryName) && CheckCountersExist(); 23 | } 24 | 25 | static bool CheckCountersExist() 26 | { 27 | foreach (var counter in Counters) 28 | { 29 | if (!PerformanceCounterCategory.CounterExists(counter.CounterName, categoryName)) 30 | return false; 31 | } 32 | return true; 33 | } 34 | 35 | public bool DoesCategoryExist() 36 | { 37 | return PerformanceCounterCategory.Exists(categoryName); 38 | } 39 | 40 | public void DeleteCategory() 41 | { 42 | PerformanceCounterCategory.Delete(categoryName); 43 | } 44 | 45 | public void SetupCounters() 46 | { 47 | var counterCreationCollection = new CounterCreationDataCollection(Counters.ToArray()); 48 | PerformanceCounterCategory.Create(categoryName, "NServiceBus statistics", PerformanceCounterCategoryType.MultiInstance, counterCreationCollection); 49 | PerformanceCounter.CloseSharedResources(); // http://blog.dezfowler.com/2007/08/net-performance-counter-problems.html 50 | } 51 | 52 | static List Counters = new List 53 | { 54 | new CounterCreationData("Critical Time", "Age of the oldest message in the queue.", PerformanceCounterType.NumberOfItems32), 55 | new CounterCreationData("SLA violation countdown","Seconds until the SLA for this endpoint is breached.",PerformanceCounterType.NumberOfItems32), 56 | new CounterCreationData("# of msgs successfully processed / sec", "The current number of messages processed successfully by the transport per second.",PerformanceCounterType.RateOfCountsPerSecond32), 57 | new CounterCreationData("# of msgs pulled from the input queue /sec", "The current number of messages pulled from the input queue by the transport per second.", PerformanceCounterType.RateOfCountsPerSecond32), 58 | new CounterCreationData("# of msgs failures / sec", "The current number of failed processed messages by the transport per second.", PerformanceCounterType.RateOfCountsPerSecond32) 59 | }; 60 | } 61 | } -------------------------------------------------------------------------------- /src/NServiceBus.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Particular/NServiceBus.PowerShell/89269f5eea33d7e3d4de798237407cbec2db0002/src/NServiceBus.snk -------------------------------------------------------------------------------- /src/Setup/NServiceBus.PowerShell.aip: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 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 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | -------------------------------------------------------------------------------- /src/Setup/Res/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Particular/NServiceBus.PowerShell/89269f5eea33d7e3d4de798237407cbec2db0002/src/Setup/Res/banner.jpg -------------------------------------------------------------------------------- /src/Setup/Res/dialog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Particular/NServiceBus.PowerShell/89269f5eea33d7e3d4de798237407cbec2db0002/src/Setup/Res/dialog.jpg -------------------------------------------------------------------------------- /src/Setup/Res/particular.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Particular/NServiceBus.PowerShell/89269f5eea33d7e3d4de798237407cbec2db0002/src/Setup/Res/particular.ico -------------------------------------------------------------------------------- /src/Setup/Setup.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net452 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | $(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Caphyon\Advanced Installer@Advanced Installer Path) 18 | "$(AdvancedInstallerPath)bin\x86\AdvancedInstaller.com" 19 | NServiceBus.PowerShell.aip 20 | commands.aic 21 | 22 | 23 | 24 | 25 | 26 | 27 | $(SolutionDir)..\assets\ 28 | NServiceBus.PowerShell-$(MinVerVersion).exe 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/Setup/commands.aic: -------------------------------------------------------------------------------- 1 | ;aic 2 | SetAzureKeyVaultSecret AZURE_KEY_VAULT_CLIENT_SECRET -secret_is_env_var_name 3 | Rebuild --------------------------------------------------------------------------------