├── .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
--------------------------------------------------------------------------------