├── .editorconfig
├── .gitattributes
├── .github
└── workflows
│ └── buildMainReleaseAction.yml
├── .gitignore
├── AzurePipelineTemplate
├── DW Automation - Export & Apply.json
├── DW Automation Deployment.json
└── DW Automation Start, Stop, Pause Maps.json
├── CODE_OF_CONDUCT.md
├── DWHelperUI
├── App.config
├── App.xaml
├── App.xaml.cs
├── AssemblyInfo.cs
├── DWHelperUI.csproj
├── EditConfigForm.xaml
├── EditConfigForm.xaml.cs
├── LogoFinal.ico
├── LogoFinal.png
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Properties
│ ├── Settings.Designer.cs
│ └── Settings.settings
└── XamlHelper.cs
├── DWLibary
├── ADOWikiUpload.cs
├── ArgsHandler.cs
├── DWEnums.cs
├── DWEnvCalls.cs
├── DWHttp.cs
├── DWLibary.csproj
├── DWSettings.cs
├── Drivers
│ └── edgeversion.txt
├── EdgeUniversal.cs
├── EncryptionHelper.cs
├── EncryptionKeyGenerator.cs
├── Engines
│ ├── DWADOWikiEngine.cs
│ ├── DWCommonEngine.cs
│ ├── DWComparison.cs
│ ├── DWMapEngine.cs
│ ├── DWSolutionEngine.cs
│ └── ResetLinkEngine.cs
├── EnvGatewayCombination.cs
├── GlobalVar.cs
├── HttpClientWithRetry.cs
├── MFAGen.cs
├── Options.cs
├── ServicePrincipalAuth.cs
├── Struct
│ ├── DWConnectionSet.cs
│ ├── DWEnvironment.cs
│ ├── DWFieldMapping.cs
│ ├── DWMaps.cs
│ ├── DWWikiOverview.cs
│ ├── Groups.cs
│ ├── InitialSyncDetails.cs
│ ├── IntegrationKeys.cs
│ ├── LoginData.cs
│ ├── MapConfig.cs
│ ├── MapDependency.cs
│ ├── MapsHelper.cs
│ ├── ResetLinkPayload.cs
│ ├── SolutionHelpers.cs
│ └── SolutionList.cs
└── TokenRefresh.cs
├── DualWriteHelper.sln
├── DualWriteHelper
├── App.config
├── AppExecution.cs
├── DWHelperCMD.csproj
├── DWHostedService.cs
├── ExampleRun-AllParameters.bat
├── ExampleRun-ExportMaps - Copy.bat
├── ExampleRun-adoWikiUpload.bat
├── ExampleRun-customConfig.bat
├── ExampleRun-deployment.bat
├── ExampleRun-initalSync.bat
├── ExampleRunCMD.bat
└── Main.cs
├── LICENSE
├── README.md
├── SECURITY.md
└── SUPPORT.md
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 |
3 | # CS8600: Converting null literal or possible null value to non-nullable type.
4 | dotnet_diagnostic.CS8600.severity = none
5 | csharp_indent_labels = one_less_than_current
6 | csharp_using_directive_placement = outside_namespace:silent
7 | csharp_prefer_simple_using_statement = true:suggestion
8 | csharp_prefer_braces = true:silent
9 | csharp_style_namespace_declarations = block_scoped:silent
10 | csharp_style_prefer_method_group_conversion = true:silent
11 | csharp_style_prefer_top_level_statements = true:silent
12 | csharp_style_expression_bodied_methods = false:silent
13 | csharp_style_expression_bodied_constructors = false:silent
14 | csharp_style_expression_bodied_operators = false:silent
15 | csharp_style_expression_bodied_properties = true:silent
16 | csharp_style_expression_bodied_indexers = true:silent
17 | csharp_style_expression_bodied_accessors = true:silent
18 | csharp_style_expression_bodied_lambdas = true:silent
19 | csharp_style_expression_bodied_local_functions = false:silent
20 |
21 | [*.{cs,vb}]
22 | dotnet_style_operator_placement_when_wrapping = beginning_of_line
23 | tab_width = 4
24 | indent_size = 4
25 | end_of_line = crlf
26 | dotnet_style_coalesce_expression = true:suggestion
27 | dotnet_style_null_propagation = true:suggestion
28 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
29 | dotnet_style_prefer_auto_properties = true:silent
30 | dotnet_style_object_initializer = true:suggestion
31 | dotnet_style_collection_initializer = true:suggestion
32 | dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
33 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent
34 | dotnet_style_prefer_conditional_expression_over_return = true:silent
35 | dotnet_style_explicit_tuple_names = true:suggestion
36 | dotnet_style_prefer_inferred_tuple_names = true:suggestion
37 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
38 | dotnet_style_prefer_compound_assignment = true:suggestion
39 | dotnet_style_prefer_simplified_interpolation = true:suggestion
40 | [*.{cs,vb}]
41 | #### Naming styles ####
42 |
43 | # Naming rules
44 |
45 | dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
46 | dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
47 | dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
48 |
49 | dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
50 | dotnet_naming_rule.types_should_be_pascal_case.symbols = types
51 | dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
52 |
53 | dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
54 | dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
55 | dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
56 |
57 | # Symbol specifications
58 |
59 | dotnet_naming_symbols.interface.applicable_kinds = interface
60 | dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
61 | dotnet_naming_symbols.interface.required_modifiers =
62 |
63 | dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
64 | dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
65 | dotnet_naming_symbols.types.required_modifiers =
66 |
67 | dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
68 | dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
69 | dotnet_naming_symbols.non_field_members.required_modifiers =
70 |
71 | # Naming styles
72 |
73 | dotnet_naming_style.begins_with_i.required_prefix = I
74 | dotnet_naming_style.begins_with_i.required_suffix =
75 | dotnet_naming_style.begins_with_i.word_separator =
76 | dotnet_naming_style.begins_with_i.capitalization = pascal_case
77 |
78 | dotnet_naming_style.pascal_case.required_prefix =
79 | dotnet_naming_style.pascal_case.required_suffix =
80 | dotnet_naming_style.pascal_case.word_separator =
81 | dotnet_naming_style.pascal_case.capitalization = pascal_case
82 |
83 | dotnet_naming_style.pascal_case.required_prefix =
84 | dotnet_naming_style.pascal_case.required_suffix =
85 | dotnet_naming_style.pascal_case.word_separator =
86 | dotnet_naming_style.pascal_case.capitalization = pascal_case
87 | dotnet_style_namespace_match_folder = true:suggestion
88 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/workflows/buildMainReleaseAction.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a .NET project
2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
3 |
4 | name: .NET
5 |
6 | on:
7 | push:
8 | branches: [ "main" ]
9 | pull_request:
10 | branches: [ "main" ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: windows-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v3
19 | - name: Setup .NET
20 | uses: actions/setup-dotnet@v3
21 | with:
22 | dotnet-version: 6.0.x
23 | - name: Restore dependencies
24 | run: dotnet restore
25 | - name: Build
26 | run: dotnet build --no-restore --configuration "Release"
27 | - name: Test
28 | run: dotnet test --no-build --verbosity normal
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
364 | /DualWriteHelper01/CCBA.config
365 | /DualWriteHelper01/tokens.txt
366 | /DualWriteHelper/DEBUGArgs.txt
367 | /DualWriteHelper/DEMO.config
368 | /DualWriteHelper/TEST.config
369 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/DWHelperUI/App.config:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | True
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | False
27 |
28 |
29 | False
30 |
31 |
32 |
33 |
34 |
35 | All
36 |
37 |
38 | DWHelperCMD.dll.config
39 |
40 |
41 | Information
42 |
43 |
44 | Default
45 |
46 |
47 |
48 |
49 |
50 | False
51 |
52 |
53 | False
54 |
55 |
56 | Default
57 |
58 |
59 | False
60 |
61 |
62 | True
63 |
64 |
65 | True
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/DWHelperUI/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/DWHelperUI/App.xaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Configuration;
7 | using System.Data;
8 | using System.Linq;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 |
12 | namespace DWHelperUI
13 | {
14 | ///
15 | /// Interaction logic for App.xaml
16 | ///
17 | public partial class App : Application
18 | {
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/DWHelperUI/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(
4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
5 | //(used if a resource is not found in the page,
6 | // or application resource dictionaries)
7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
8 | //(used if a resource is not found in the page,
9 | // app, or any theme specific resource dictionaries)
10 | )]
11 |
--------------------------------------------------------------------------------
/DWHelperUI/DWHelperUI.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1.0.11
5 | WinExe
6 | net9.0-windows7.0
7 | enable
8 | true
9 | LogoFinal.ico
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | PreserveNewest
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | True
39 | True
40 | Settings.settings
41 |
42 |
43 |
44 |
45 |
46 | SettingsSingleFileGenerator
47 | Settings.Designer.cs
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/DWHelperUI/EditConfigForm.xaml.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using CommandLine;
5 | using DWLibary;
6 | using Microsoft.Identity.Client;
7 | using Microsoft.VisualStudio.Services.CircuitBreaker;
8 | using System;
9 | using System.Collections.Generic;
10 | using System.Collections.ObjectModel;
11 | using System.Collections.Specialized;
12 | using System.Configuration;
13 | using System.Globalization;
14 | using System.Linq;
15 | using System.Text;
16 | using System.Threading.Tasks;
17 | using System.Windows;
18 | using System.Windows.Controls;
19 | using System.Windows.Data;
20 | using System.Windows.Documents;
21 | using System.Windows.Input;
22 | using System.Windows.Media;
23 | using System.Windows.Media.Imaging;
24 | using System.Windows.Shapes;
25 | using System.Xml.Linq;
26 |
27 | namespace DWHelperUI
28 | {
29 | ///
30 | /// Interaction logic for EditConfigForm.xaml
31 | ///
32 | public partial class EditConfigForm
33 | {
34 | public string configName { get; set; }
35 | ObservableCollection mapConfigsContent;
36 |
37 | public EditConfigForm(string configName)
38 | {
39 | InitializeComponent();
40 | this.configName = configName;
41 |
42 | initConfig();
43 | getAppSettingsGridData();
44 | getSolutionsGridData();
45 | getGroupsGridData();
46 | getADOGridData();
47 | getMapsGridData();
48 | }
49 |
50 | private void initConfig()
51 | {
52 | GlobalVar.configFileName = configName;
53 | GlobalVar.initConfig();
54 | }
55 |
56 | private void getADOGridData()
57 | {
58 | List gridContent = GlobalVar.dwSettings.ADOWikiParameters.Cast().ToList();
59 |
60 | setVisibility(adoSettings);
61 |
62 | adoSettings.ItemsSource = gridContent;
63 |
64 | }
65 |
66 | private void getAppSettingsGridData()
67 | {
68 | List gridContent = GlobalVar.config.AppSettings.Settings.Cast().ToList();
69 |
70 | setVisibility(appSettings);
71 |
72 |
73 |
74 |
75 | appSettings.ItemsSource = gridContent;
76 |
77 | }
78 |
79 |
80 | private void getSolutionsGridData()
81 | {
82 | List gridContent = GlobalVar.dwSettings.Solutions.Cast().ToList();
83 |
84 | setVisibility(solutions);
85 |
86 | solutions.ItemsSource = gridContent;
87 |
88 | }
89 |
90 | private void getGroupsGridData()
91 | {
92 | List gridContent = GlobalVar.dwSettings.Groups.Cast().ToList();
93 |
94 | setVisibility(groups);
95 |
96 | groups.ItemsSource = gridContent;
97 |
98 | }
99 |
100 | private void setVisibility(DataGrid _grid)
101 | {
102 | _grid.AutoGenerateColumns = false;
103 | var properties = typeof(T).GetProperties();
104 |
105 | foreach (var prop in properties)
106 | {
107 | dynamic column = new DataGridTextColumn();
108 |
109 |
110 |
111 | if (prop.Name == "executionMode")
112 | {
113 | column = new DataGridTextColumn();
114 | }
115 |
116 |
117 |
118 | column.Binding = new Binding(prop.Name);
119 | column.Header = prop.Name;
120 |
121 | if (typeof(T).IsAssignableFrom(prop.DeclaringType) && prop.IsDefined(typeof(ConfigurationPropertyAttribute), false))
122 | {
123 | column.Visibility = Visibility.Visible;
124 | }
125 | else
126 | {
127 | column.Visibility = Visibility.Hidden;
128 | }
129 | _grid.Columns.Add(column);
130 | }
131 | }
132 |
133 | private void getMapsGridData()
134 | {
135 |
136 | mapConfigsContent = new ObservableCollection(GlobalVar.dwSettings.MapConfigs.Cast().ToList());
137 | setVisibility(mapConfig);
138 | mapConfig.ItemsSource = mapConfigsContent;
139 |
140 | }
141 |
142 | private void saveSettings()
143 | {
144 | clearFilter();
145 |
146 | GlobalVar.dwSettings.ADOWikiParameters.Clear();
147 |
148 | foreach (var item in adoSettings.Items)
149 | {
150 | if (item is ADOWikiParameter)
151 | GlobalVar.dwSettings.ADOWikiParameters.Add((ADOWikiParameter)item);
152 | }
153 |
154 |
155 | GlobalVar.dwSettings.MapConfigs.Clear();
156 | foreach (var item in mapConfig.Items)
157 | {
158 | if (item is MapConfig)
159 | GlobalVar.dwSettings.MapConfigs.Add((MapConfig)item);
160 | }
161 |
162 | GlobalVar.dwSettings.Groups.Clear();
163 | foreach (var item in groups.Items)
164 | {
165 | if (item is Group)
166 | GlobalVar.dwSettings.Groups.Add((Group)item);
167 | }
168 |
169 |
170 | GlobalVar.dwSettings.Solutions.Clear();
171 | foreach (var item in solutions.Items)
172 | {
173 | if (item is Solution)
174 | GlobalVar.dwSettings.Solutions.Add((Solution)item);
175 | }
176 |
177 |
178 | GlobalVar.config.AppSettings.Settings.Clear();
179 | foreach (var item in appSettings.Items)
180 | {
181 | if (item is KeyValueConfigurationElement)
182 | GlobalVar.config.AppSettings.Settings.Add((KeyValueConfigurationElement)item);
183 | }
184 |
185 | GlobalVar.config.Save(ConfigurationSaveMode.Modified);
186 | }
187 |
188 | private void SaveSettings_Click(object sender, RoutedEventArgs e)
189 | {
190 | saveSettings();
191 |
192 | }
193 |
194 | private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
195 | {
196 | MessageBoxResult result = MessageBox.Show("Do you want to save your settings before closing?", "Confirm", MessageBoxButton.YesNo, MessageBoxImage.Question);
197 | switch (result)
198 | {
199 | case MessageBoxResult.Yes:
200 | // Save settings and continue closing the window
201 | saveSettings();
202 | break;
203 | case MessageBoxResult.No:
204 | // Do not save settings and continue closing the window
205 | break;
206 | }
207 | }
208 |
209 | private void filterGrid()
210 | {
211 | var view = CollectionViewSource.GetDefaultView(mapConfig.ItemsSource);
212 | view.Filter = o =>
213 | {
214 | var item = o as MapConfig;
215 | var properties = item.GetType().GetProperties();
216 | foreach (var property in properties)
217 | {
218 | var value = property.GetValue(item, null);
219 | if (value != null && value.ToString().ToLower().Contains(SearchString.Text.ToLower()))
220 | {
221 | return true;
222 | }
223 | }
224 | return false;
225 | };
226 | }
227 | private void Close_Click(object sender, RoutedEventArgs e)
228 | {
229 | this.Close();
230 | }
231 |
232 | private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
233 | {
234 | if (e.ChangedButton == MouseButton.Left)
235 | {
236 | this.DragMove();
237 | }
238 | }
239 |
240 | private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
241 | {
242 | if (e.ClickCount == 2)
243 | {
244 | this.WindowState = WindowState.Normal;
245 | }
246 | }
247 |
248 | private void Filter_Click(object sender, RoutedEventArgs e)
249 | {
250 | filterGrid();
251 | }
252 |
253 | private void ClearFilter_Click(object sender, RoutedEventArgs e)
254 | {
255 | clearFilter();
256 | }
257 |
258 | private void clearFilter()
259 | {
260 | SearchString.Clear();
261 | filterGrid();
262 | }
263 |
264 | private void moveUp_Click(object sender, RoutedEventArgs e)
265 | {
266 |
267 | int selectedIndex = mapConfig.SelectedIndex;
268 | if (selectedIndex > 0)
269 | {
270 | int newIndex = selectedIndex - 1;
271 |
272 | MapConfig selectedItem = mapConfig.SelectedItem as MapConfig;
273 | if (selectedItem != null)
274 | {
275 | mapConfigsContent.RemoveAt(selectedIndex);
276 | mapConfigsContent.Insert(newIndex, selectedItem);
277 | mapConfig.SelectedItem = mapConfig.Items[newIndex];
278 | mapConfig.Focus();
279 | }
280 | }
281 |
282 | }
283 |
284 | private void moveDown_Click(object sender, RoutedEventArgs e)
285 | {
286 | int selectedIndex = mapConfig.SelectedIndex;
287 | if (selectedIndex > 0)
288 | {
289 |
290 | int newIndex = selectedIndex + 1;
291 | MapConfig selectedItem = mapConfig.SelectedItem as MapConfig;
292 |
293 | if (newIndex < mapConfig.Items.Count && selectedItem != null)
294 | {
295 | mapConfigsContent.RemoveAt(selectedIndex);
296 | mapConfigsContent.Insert(newIndex, selectedItem);
297 | mapConfig.SelectedItem = mapConfig.Items[newIndex];
298 | mapConfig.Focus();
299 | }
300 | }
301 | }
302 | }
303 |
304 |
305 |
306 | }
307 |
--------------------------------------------------------------------------------
/DWHelperUI/LogoFinal.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/Dual-write-automations/04b956efc7b6e4162ad90ff0f2dc4872355c311e/DWHelperUI/LogoFinal.ico
--------------------------------------------------------------------------------
/DWHelperUI/LogoFinal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/Dual-write-automations/04b956efc7b6e4162ad90ff0f2dc4872355c311e/DWHelperUI/LogoFinal.png
--------------------------------------------------------------------------------
/DWHelperUI/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace DWHelperUI.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.11.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.UserScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
29 | public bool applySolutionCheckbox {
30 | get {
31 | return ((bool)(this["applySolutionCheckbox"]));
32 | }
33 | set {
34 | this["applySolutionCheckbox"] = value;
35 | }
36 | }
37 |
38 | [global::System.Configuration.UserScopedSettingAttribute()]
39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
40 | public global::System.Collections.Specialized.StringCollection envList {
41 | get {
42 | return ((global::System.Collections.Specialized.StringCollection)(this["envList"]));
43 | }
44 | set {
45 | this["envList"] = value;
46 | }
47 | }
48 |
49 | [global::System.Configuration.UserScopedSettingAttribute()]
50 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
51 | [global::System.Configuration.DefaultSettingValueAttribute("")]
52 | public string envURL {
53 | get {
54 | return ((string)(this["envURL"]));
55 | }
56 | set {
57 | this["envURL"] = value;
58 | }
59 | }
60 |
61 | [global::System.Configuration.UserScopedSettingAttribute()]
62 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
63 | [global::System.Configuration.DefaultSettingValueAttribute("")]
64 | public string password {
65 | get {
66 | return ((string)(this["password"]));
67 | }
68 | set {
69 | this["password"] = value;
70 | }
71 | }
72 |
73 | [global::System.Configuration.UserScopedSettingAttribute()]
74 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
75 | [global::System.Configuration.DefaultSettingValueAttribute("")]
76 | public string username {
77 | get {
78 | return ((string)(this["username"]));
79 | }
80 | set {
81 | this["username"] = value;
82 | }
83 | }
84 |
85 | [global::System.Configuration.UserScopedSettingAttribute()]
86 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
87 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
88 | public bool adowikiupload {
89 | get {
90 | return ((bool)(this["adowikiupload"]));
91 | }
92 | set {
93 | this["adowikiupload"] = value;
94 | }
95 | }
96 |
97 | [global::System.Configuration.UserScopedSettingAttribute()]
98 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
99 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
100 | public bool exportConfig {
101 | get {
102 | return ((bool)(this["exportConfig"]));
103 | }
104 | set {
105 | this["exportConfig"] = value;
106 | }
107 | }
108 |
109 | [global::System.Configuration.UserScopedSettingAttribute()]
110 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
111 | [global::System.Configuration.DefaultSettingValueAttribute("")]
112 | public string runmode {
113 | get {
114 | return ((string)(this["runmode"]));
115 | }
116 | set {
117 | this["runmode"] = value;
118 | }
119 | }
120 |
121 | [global::System.Configuration.UserScopedSettingAttribute()]
122 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
123 | [global::System.Configuration.DefaultSettingValueAttribute("All")]
124 | public string exportStatus {
125 | get {
126 | return ((string)(this["exportStatus"]));
127 | }
128 | set {
129 | this["exportStatus"] = value;
130 | }
131 | }
132 |
133 | [global::System.Configuration.UserScopedSettingAttribute()]
134 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
135 | [global::System.Configuration.DefaultSettingValueAttribute("DWHelperCMD.dll.config")]
136 | public string configName {
137 | get {
138 | return ((string)(this["configName"]));
139 | }
140 | set {
141 | this["configName"] = value;
142 | }
143 | }
144 |
145 | [global::System.Configuration.UserScopedSettingAttribute()]
146 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
147 | [global::System.Configuration.DefaultSettingValueAttribute("Information")]
148 | public string logLevel {
149 | get {
150 | return ((string)(this["logLevel"]));
151 | }
152 | set {
153 | this["logLevel"] = value;
154 | }
155 | }
156 |
157 | [global::System.Configuration.UserScopedSettingAttribute()]
158 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
159 | [global::System.Configuration.DefaultSettingValueAttribute("Default")]
160 | public string exportOption {
161 | get {
162 | return ((string)(this["exportOption"]));
163 | }
164 | set {
165 | this["exportOption"] = value;
166 | }
167 | }
168 |
169 | [global::System.Configuration.UserScopedSettingAttribute()]
170 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
171 | [global::System.Configuration.DefaultSettingValueAttribute("")]
172 | public string targetFO {
173 | get {
174 | return ((string)(this["targetFO"]));
175 | }
176 | set {
177 | this["targetFO"] = value;
178 | }
179 | }
180 |
181 | [global::System.Configuration.UserScopedSettingAttribute()]
182 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
183 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
184 | public bool forceReset {
185 | get {
186 | return ((bool)(this["forceReset"]));
187 | }
188 | set {
189 | this["forceReset"] = value;
190 | }
191 | }
192 |
193 | [global::System.Configuration.UserScopedSettingAttribute()]
194 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
195 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
196 | public bool disablePrivateBrowser {
197 | get {
198 | return ((bool)(this["disablePrivateBrowser"]));
199 | }
200 | set {
201 | this["disablePrivateBrowser"] = value;
202 | }
203 | }
204 |
205 | [global::System.Configuration.UserScopedSettingAttribute()]
206 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
207 | [global::System.Configuration.DefaultSettingValueAttribute("Default")]
208 | public string catchUpSetting {
209 | get {
210 | return ((string)(this["catchUpSetting"]));
211 | }
212 | set {
213 | this["catchUpSetting"] = value;
214 | }
215 | }
216 |
217 | [global::System.Configuration.UserScopedSettingAttribute()]
218 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
219 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
220 | public bool lightMode {
221 | get {
222 | return ((bool)(this["lightMode"]));
223 | }
224 | set {
225 | this["lightMode"] = value;
226 | }
227 | }
228 |
229 | [global::System.Configuration.UserScopedSettingAttribute()]
230 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
231 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
232 | public bool darkMode {
233 | get {
234 | return ((bool)(this["darkMode"]));
235 | }
236 | set {
237 | this["darkMode"] = value;
238 | }
239 | }
240 |
241 | [global::System.Configuration.UserScopedSettingAttribute()]
242 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
243 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
244 | public bool upgradeRequired {
245 | get {
246 | return ((bool)(this["upgradeRequired"]));
247 | }
248 | set {
249 | this["upgradeRequired"] = value;
250 | }
251 | }
252 |
253 | [global::System.Configuration.UserScopedSettingAttribute()]
254 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
255 | [global::System.Configuration.DefaultSettingValueAttribute("")]
256 | public string EncryptionKey {
257 | get {
258 | return ((string)(this["EncryptionKey"]));
259 | }
260 | set {
261 | this["EncryptionKey"] = value;
262 | }
263 | }
264 |
265 | [global::System.Configuration.UserScopedSettingAttribute()]
266 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
267 | [global::System.Configuration.DefaultSettingValueAttribute("")]
268 | public string EncryptionIv {
269 | get {
270 | return ((string)(this["EncryptionIv"]));
271 | }
272 | set {
273 | this["EncryptionIv"] = value;
274 | }
275 | }
276 | }
277 | }
278 |
--------------------------------------------------------------------------------
/DWHelperUI/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | True
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | False
22 |
23 |
24 | False
25 |
26 |
27 |
28 |
29 |
30 | All
31 |
32 |
33 | DWHelperCMD.dll.config
34 |
35 |
36 | Information
37 |
38 |
39 | Default
40 |
41 |
42 |
43 |
44 |
45 | False
46 |
47 |
48 | False
49 |
50 |
51 | Default
52 |
53 |
54 | False
55 |
56 |
57 | True
58 |
59 |
60 | True
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/DWHelperUI/XamlHelper.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Controls;
10 | using System.Windows.Data;
11 | using System.Windows;
12 |
13 | namespace DWHelperUI
14 | {
15 | public static class Secure
16 | {
17 | private static readonly DependencyProperty PasswordInitializedProperty =
18 | DependencyProperty.RegisterAttached("PasswordInitialized", typeof(bool), typeof(Secure), new PropertyMetadata(false));
19 |
20 | private static readonly DependencyProperty SettingPasswordProperty =
21 | DependencyProperty.RegisterAttached("SettingPassword", typeof(bool), typeof(Secure), new PropertyMetadata(false));
22 |
23 | public static string GetPassword(DependencyObject obj)
24 | {
25 | return (string)obj.GetValue(PasswordProperty);
26 | }
27 | public static void SetPassword(DependencyObject obj, string value)
28 | {
29 | obj.SetValue(PasswordProperty, value);
30 | }
31 | // We play a trick here. If we set the initial value to something, it'll be set to something else when the binding kicks in,
32 | // and HandleBoundPasswordChanged will be called, which allows us to set up our event subscription.
33 | // If the binding sets us to a value which we already are, then this doesn't happen. Therefore start with a value that's
34 | // definitely unique.
35 | public static readonly DependencyProperty PasswordProperty =
36 | DependencyProperty.RegisterAttached("Password", typeof(string), typeof(Secure),
37 | new FrameworkPropertyMetadata(Guid.NewGuid().ToString(), HandleBoundPasswordChanged)
38 | {
39 | BindsTwoWayByDefault = true,
40 | DefaultUpdateSourceTrigger = UpdateSourceTrigger.LostFocus // Match the default on Binding
41 | });
42 |
43 | private static void HandleBoundPasswordChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
44 | {
45 | var passwordBox = dp as PasswordBox;
46 | if (passwordBox == null)
47 | return;
48 |
49 | // If we're being called because we set the value of the property we're bound to (from inside
50 | // HandlePasswordChanged, then do nothing - we already have the latest value).
51 | if ((bool)passwordBox.GetValue(SettingPasswordProperty))
52 | return;
53 |
54 | // If this is the initial set (see the comment on PasswordProperty), set ourselves up
55 | if (!(bool)passwordBox.GetValue(PasswordInitializedProperty))
56 | {
57 | passwordBox.SetValue(PasswordInitializedProperty, true);
58 | passwordBox.PasswordChanged += HandlePasswordChanged;
59 | }
60 |
61 | passwordBox.Password = e.NewValue as string;
62 | }
63 |
64 | private static void HandlePasswordChanged(object sender, RoutedEventArgs e)
65 | {
66 | var passwordBox = (PasswordBox)sender;
67 | passwordBox.SetValue(SettingPasswordProperty, true);
68 | SetPassword(passwordBox, passwordBox.Password);
69 | passwordBox.SetValue(SettingPasswordProperty, false);
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/DWLibary/ADOWikiUpload.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using Microsoft.TeamFoundation.SourceControl.WebApi;
5 | using Microsoft.VisualStudio.Services.Common;
6 | using Microsoft.VisualStudio.Services.WebApi;
7 | using Microsoft.TeamFoundation.Wiki.WebApi;
8 | using System;
9 | using System.Collections.Generic;
10 | using System.Linq;
11 | using System.Text;
12 | using System.Threading.Tasks;
13 | using Microsoft.VisualBasic;
14 | using System.Diagnostics.Metrics;
15 | using System.Configuration;
16 | using System.IO;
17 | using Microsoft.Extensions.Logging;
18 | using Azure;
19 |
20 | namespace DWLibary
21 | {
22 |
23 |
24 |
25 | public class ADOWikiUpload
26 | {
27 |
28 | string projectName = "";
29 |
30 | string pat = "";
31 | public string wikiPath = "";
32 | string wikiName = "";
33 | string orgURL = "";
34 | public bool useUpload = false;
35 |
36 | private WikiHttpClient wikiClient;
37 |
38 | private WikiV2 wiki;
39 |
40 | ILogger logger;
41 |
42 | public ADOWikiUpload(ILogger _logger)
43 | {
44 | logger = _logger;
45 | loadParamaters();
46 |
47 | }
48 |
49 |
50 | private void loadParamaters()
51 | {
52 | foreach (ADOWikiParameter param in GlobalVar.dwSettings.ADOWikiParameters)
53 | {
54 | switch (param.Key.ToUpper())
55 | {
56 | case "USEADOWIKIUPLOAD":
57 | if (GlobalVar.useadowikiupload)
58 | useUpload = GlobalVar.useadowikiupload;
59 | else
60 | useUpload = Convert.ToBoolean(param.Value);
61 |
62 | break;
63 |
64 | case "ACCESSTOKEN":
65 | if (GlobalVar.adotoken != String.Empty)
66 | pat = GlobalVar.adotoken;
67 | else
68 | pat = param.Value;
69 | break;
70 |
71 | case "PROJECTNAME":
72 | projectName = param.Value;
73 | break;
74 |
75 | case "ORGANIZATIONURL":
76 | orgURL = param.Value;
77 | break;
78 |
79 | case "WIKINAME":
80 | wikiName = param.Value;
81 | break;
82 |
83 | case "WIKIPATH":
84 | wikiPath = param.Value;
85 | break;
86 |
87 | }
88 | }
89 | }
90 |
91 | public async Task init()
92 | {
93 |
94 | if (!useUpload)
95 | return useUpload;
96 |
97 | var creds = new VssBasicCredential(string.Empty, pat);
98 |
99 | Uri baseUrl = new Uri(orgURL);
100 |
101 | wikiClient = new WikiHttpClient(baseUrl, creds);
102 |
103 | try
104 | {
105 | wiki = await wikiClient.GetWikiAsync(projectName, wikiName);
106 | }
107 | catch (Exception ex)
108 | {
109 | logger.LogError("Could not authenticate to the wiki, please check the configuration");
110 | useUpload= false;
111 | }
112 |
113 | if(wiki == null)
114 | {
115 | logger.LogError($"Could not authenticate to the wiki or wiki was not found under project {projectName}, Wiki: {wikiName} , please check the configuration and make sure your access token has Read / Write for Wiki");
116 | useUpload = false;
117 | }
118 |
119 |
120 | return useUpload;
121 |
122 |
123 | }
124 |
125 | public string CombineForward(string path1, string path2)
126 | {
127 |
128 | string ret = string.Empty;
129 |
130 |
131 | if(path1.Length > 0)
132 | {
133 | if (path1.Substring(0, 1) != "/")
134 | path1 = "/" + path1;
135 | }
136 |
137 | if(path2.Length > 0)
138 | {
139 | if(path2.Substring(path2.Length-1, 1) == "/")
140 | path2 = path2.Substring(0, path2.Length-1);
141 |
142 | }
143 |
144 | if(path1.Length > 0 && path2.Length > 0)
145 | {
146 |
147 | string endPath1 = path1.Substring(path1.Length - 1, 1);
148 | string beginPath2 = path2.Substring(0, 1);
149 |
150 | if (endPath1 != "/" && beginPath2 == "/")
151 | ret = path1 + path2;
152 |
153 | if (endPath1 == "/" && beginPath2 != "/")
154 | ret = path1 + path2;
155 |
156 | if (endPath1 != "/" && beginPath2 != "/")
157 | ret = path1 + "/" + path2;
158 |
159 | if (endPath1 == "/" && beginPath2 == "/")
160 | ret = path1 + path2.Substring(1, path2.Length - 1);
161 |
162 | }
163 |
164 |
165 | return ret;
166 |
167 | }
168 |
169 | public async Task createUpdatePage(string content, string path, bool updatePage = true)
170 | {
171 |
172 | try
173 | {
174 | if (!useUpload)
175 | return;
176 |
177 |
178 | string finalPath = CombineForward(wikiPath, path);
179 |
180 | content = $"_This Page is automatically generated, if you do makes changes it may be overwritten_{Environment.NewLine}" + content;
181 |
182 | WikiPageCreateOrUpdateParameters parameters = new WikiPageCreateOrUpdateParameters();
183 | parameters.Content = content;
184 |
185 | GitVersionDescriptor gitVersion = null;
186 | if(wiki.Versions.Any())
187 | {
188 | gitVersion = wiki.Versions.FirstOrDefault();
189 | }
190 |
191 |
192 | WikiPageResponse wikiPage = null;
193 | //parameters.
194 | try
195 | {
196 | wikiPage = await wikiClient.GetPageAsync(wiki.ProjectId, wiki.Id, finalPath);
197 | }
198 | catch { }
199 |
200 | if (wikiPage != null)
201 | {
202 | if (updatePage)
203 | await wikiClient.CreateOrUpdatePageAsync(parameters, wiki.ProjectId, wiki.Id, finalPath, wikiPage.ETag.FirstOrDefault(), null,gitVersion);
204 | }
205 | else
206 |
207 | {
208 | await wikiClient.CreateOrUpdatePageAsync(parameters, wiki.ProjectId, wiki.Id, finalPath,"",null, gitVersion);
209 | }
210 |
211 | }
212 | catch(Exception ex)
213 | {
214 | logger.LogError(ex.ToString());
215 | }
216 |
217 | }
218 |
219 | public async Task runTest()
220 | {
221 |
222 | await init();
223 |
224 | if (!useUpload)
225 | return;
226 |
227 | string finalPath = "/DualWrite Automation/something";
228 | //var wikis = await wiki.GetAllWikisAsync(); //Gets all Wikis
229 |
230 |
231 | // Get data about a specific repository
232 | // var repo = gitClient.GetRepositoryAsync(projectName, repoName).Result;
233 |
234 | WikiPageCreateOrUpdateParameters parameters = new WikiPageCreateOrUpdateParameters();
235 | parameters.Content = "Some content3";
236 |
237 |
238 | //parameters.
239 |
240 | WikiPageResponse wikiPage = null;
241 | //parameters.
242 | try
243 | {
244 | wikiPage = await wikiClient.GetPageAsync(wiki.ProjectId, wiki.Id, finalPath);
245 | }
246 | catch { }
247 |
248 |
249 |
250 | await wikiClient.CreateOrUpdatePageAsync(parameters, wiki.ProjectId, wiki.Id, finalPath, wikiPage == null ? "" : wikiPage.ETag.FirstOrDefault());
251 |
252 |
253 | }
254 | }
255 | }
256 |
--------------------------------------------------------------------------------
/DWLibary/ArgsHandler.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using CommandLine;
7 |
8 | namespace DWLibary
9 | {
10 | public class ArgsHandler
11 | {
12 | public Options parsedOptions;
13 |
14 | public void parseCommands(string[] args)
15 | {
16 |
17 | var parser = new CommandLine.Parser(s =>
18 | {
19 | s.CaseSensitive = false;
20 | s.CaseInsensitiveEnumValues = true;
21 | });
22 | parser.ParseArguments(args)
23 | .WithParsed(o => {
24 | // parsing successful; go ahead and run the app
25 | GlobalVar.username = o.username;
26 | GlobalVar.password = o.password;
27 |
28 | GlobalVar.foEnv = parseUriHostname(o.environment);
29 |
30 |
31 | GlobalVar.configFileName = o.configFileName;
32 | GlobalVar.mfasecret = o.mfasecret;
33 | GlobalVar.useadowikiupload = o.useadowikiupload;
34 | GlobalVar.adotoken = o.adotoken;
35 |
36 | GlobalVar.runMode = o.runmode;
37 | GlobalVar.exportState = o.status;
38 | GlobalVar.exportOption = o.exportOption;
39 |
40 | GlobalVar.noSolutions = o.noSolutions;
41 |
42 | GlobalVar.newConfigFileName = o.newConfigFileName;
43 |
44 | parsedOptions = o;
45 |
46 |
47 |
48 | o.targetenvironment = parseUriHostname(o.targetenvironment);
49 | GlobalVar.parsedOptions = o;
50 |
51 |
52 | Console.WriteLine("Commandline arguments parsed and set");
53 |
54 | })
55 | .WithNotParsed(e => {
56 |
57 | foreach (var error in e)
58 | {
59 | if (error is NamedError namedError)
60 | {
61 | Console.WriteLine($"Failed to parse parameter: {namedError.NameInfo.NameText}");
62 | }
63 | else
64 | {
65 | Console.WriteLine(error.ToString());
66 | }
67 | }
68 | // parsing unsuccessful; deal with parsing errors
69 | throw new Exception("Commandline parameters wrong");
70 |
71 |
72 | });
73 | }
74 |
75 |
76 | private string parseUriHostname(string url)
77 | {
78 |
79 | string ret = String.Empty;
80 |
81 | if(url == null || url.Length == 0)
82 | {
83 | return ret;
84 | }
85 |
86 | url = url.Trim();
87 |
88 | UriBuilder builder = new UriBuilder(url);
89 | if (builder.Uri != null)
90 | {
91 | ret = builder.Uri.Host;
92 | }
93 |
94 |
95 | return ret;
96 |
97 |
98 | }
99 |
100 |
101 |
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/DWLibary/DWEnums.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.ComponentModel;
7 | using System.Linq;
8 | using System.Reflection;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace DWLibary
13 | {
14 | public class DWEnums
15 | {
16 | public enum ExecutionMode
17 | {
18 | parallel,
19 | sequential
20 | };
21 |
22 |
23 | public enum StartStop
24 | {
25 | none,
26 | start,
27 | stop,
28 | pause,
29 | resume,
30 | init = 8
31 | };
32 |
33 | public enum CatchUpSyncOption
34 | {
35 | [Description("Catch up synchronization of queued records")]
36 | Default,
37 | [Description("Skip to live synchronization preserving queued records to catch-up errors for retry")]
38 | BackendQueueProcessing,
39 | [Description("Skip to live synchronization and discard queued records")]
40 | DeleteQueueProcessing
41 | }
42 |
43 | public enum MapStatus
44 | {
45 | None = 0,
46 | Stopped = 1,
47 | InitialSync = 2,
48 | CatchUp = 3,
49 | Running = 4,
50 | Paused = 5,
51 | //Paused = 4,
52 | NotRunning = 6,
53 |
54 | Keep = 99,
55 | All = 100
56 | };
57 |
58 | public enum RequestStatus
59 | {
60 | Waiting = 1,
61 | Completed = 2,
62 | Error = 3
63 | };
64 |
65 | public enum ExceptionHandling
66 | {
67 | ignore,
68 | skip,
69 | stop
70 |
71 | };
72 |
73 | public enum ExportOptions
74 | {
75 | [Description("Default export, any Author, latest version")]
76 | Default = 0,
77 | [Description("Exact version & author")]
78 | precise = 1,
79 | }
80 |
81 | public enum DWSyncDirection
82 | {
83 | [Description("FO <-> CE")]
84 | Both = 3,
85 | [Description("FO -> CE")]
86 | FOOnly = 1,
87 | [Description("FO <- CE")]
88 | CEOnly = 2
89 | }
90 |
91 | public enum DataMaster
92 | {
93 | [Description("CRM")]
94 | CE = 0,
95 | [Description("AX")]
96 | FO = 1
97 |
98 | };
99 |
100 | public enum RunMode
101 | {
102 | [Description("Default from configuration")]
103 | none,
104 | [Description("Deploy maps")]
105 | deployment,
106 | [Description("Deploy and Initial sync where set in config")]
107 | deployInitialSync,
108 | [Description("Start maps")]
109 | start,
110 | [Description("Stop maps")]
111 | stop,
112 | [Description("Pause maps")]
113 | pause,
114 | [Description("Export configuration")]
115 | export,
116 | [Description("Wiki upload")]
117 | wikiUpload,
118 | [Description("Compare environment")]
119 | compare,
120 | [Description("Reset link")]
121 | resetLink
122 | };
123 |
124 |
125 | public static T GetValueFromDescription(string description) where T : Enum
126 | {
127 | foreach (var field in typeof(T).GetFields())
128 | {
129 | if (Attribute.GetCustomAttribute(field,
130 | typeof(DescriptionAttribute)) is DescriptionAttribute attribute)
131 | {
132 | if (attribute.Description == description)
133 | return (T)field.GetValue(null);
134 | }
135 | else
136 | {
137 | if (field.Name == description)
138 | return (T)field.GetValue(null);
139 | }
140 | }
141 |
142 | //throw new ArgumentException("Not found.", nameof(description));
143 | return default(T);
144 | }
145 | public static string DescriptionAttr(T source)
146 | {
147 | FieldInfo fi = source.GetType().GetField(source.ToString());
148 |
149 | DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
150 | typeof(DescriptionAttribute), false);
151 |
152 | if (attributes != null && attributes.Length > 0) return attributes[0].Description;
153 | else return source.ToString();
154 | }
155 |
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/DWLibary/DWEnvCalls.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using DWLibary.Struct;
5 | using Newtonsoft.Json;
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 |
12 | namespace DWLibary
13 | {
14 | public class DWEnvCalls
15 | {
16 | DWEnvironment env;
17 |
18 |
19 | public async Task getEnvironment()
20 | {
21 | DWEnvironment environment = new DWEnvironment();
22 | try
23 | {
24 | HttpClient client = new HttpClientWithRetry();
25 | DWHttp dW = new DWHttp();
26 | HttpRequestMessage req = dW.buildDefaultHttpRequestGet();
27 |
28 | UriBuilder uriBuilder = new UriBuilder(req.RequestUri);
29 | uriBuilder.Path += $"Environments";
30 | uriBuilder.Query = $"targetType=AX&identifier={GlobalVar.foEnv}";
31 |
32 | req.RequestUri = uriBuilder.Uri;
33 |
34 | var response = await client.SendAsync(req);
35 |
36 | string content = await response.Content.ReadAsStringAsync();
37 | environment = JsonConvert.DeserializeObject>(content)[0];
38 | environment.foEnvironment = GlobalVar.foEnv;
39 |
40 |
41 |
42 | }
43 | catch (Exception ex)
44 | {
45 |
46 | }
47 |
48 | return environment;
49 |
50 | }
51 |
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/DWLibary/DWHttp.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using DWLibary.Struct;
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 |
11 | namespace DWLibary
12 | {
13 | public class DWHttp
14 | {
15 |
16 | HttpRequestMessage _httpRequest;
17 | DWEnvironment env;
18 |
19 | private const string CustomUserAgent = "DualWriteHelper/1.0 (Windows NT 10.0; Win64; x64)";
20 |
21 | public DWHttp(DWEnvironment _env = default)
22 | {
23 | env = _env;
24 | }
25 |
26 |
27 | public HttpRequestMessage buildDefaultHttpRequestPost()
28 | {
29 | _httpRequest = new HttpRequestMessage();
30 |
31 |
32 | _httpRequest.Method = HttpMethod.Post;
33 | _httpRequest.Headers.Add("Accept", "application/json");
34 | _httpRequest.Headers.Add("Origin", GlobalVar.dataintegratorURL.AbsoluteUri);
35 | _httpRequest.Headers.Add("User-Agent", CustomUserAgent);
36 |
37 | _httpRequest.RequestUri = buildReqUri();
38 | buildAuth();
39 |
40 |
41 | return _httpRequest;
42 | }
43 |
44 | private Uri buildReqUri()
45 | {
46 | Uri ret = null;
47 |
48 | if (GlobalVar.baseUrl != null && GlobalVar.baseUrl.Length > 0)
49 | {
50 | UriBuilder uriBuilder = new UriBuilder(GlobalVar.baseUrl);
51 | uriBuilder.Path = "/api/DualWriteManagement/1.0/";
52 |
53 | ret = uriBuilder.Uri;
54 | }
55 |
56 | return ret;
57 | }
58 |
59 | public HttpRequestMessage buildDefaultHttpRequestGet()
60 | {
61 | try
62 | {
63 | _httpRequest = new HttpRequestMessage();
64 |
65 | _httpRequest.Method = HttpMethod.Get;
66 |
67 | _httpRequest.RequestUri = buildReqUri();
68 |
69 | buildAuth();
70 | }
71 | catch (Exception ex)
72 | {
73 |
74 | }
75 |
76 |
77 | return _httpRequest;
78 | }
79 |
80 | private void buildAuth()
81 | {
82 |
83 | LoginData localLogin = null;
84 |
85 | if(env.foEnvironment != null)
86 | {
87 | localLogin = GlobalVar.savedTokens.Where(x => x.environment.ToUpper().Equals(env.foEnvironment.ToUpper())).FirstOrDefault();
88 | }
89 |
90 | _httpRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", localLogin != null ? localLogin.access_token : GlobalVar.loginData.access_token);
91 | }
92 |
93 |
94 |
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/DWLibary/DWLibary.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 |
8 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | PreserveNewest
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/DWLibary/DWSettings.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation.
2 | // Licensed under the MIT license.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Configuration;
7 | using System.Linq;
8 | using System.Text;
9 | using System.Threading.Tasks;
10 | using System.Xml;
11 | using System.Xml.Serialization;
12 |
13 | namespace DWLibary
14 | {
15 |
16 | public class ADOWikiParameter : ConfigurationSection
17 | {
18 |
19 | public ADOWikiParameter() { }
20 |
21 | public ADOWikiParameter(string key)
22 | {
23 | Key = key;
24 | //ReportType = reportType;
25 | }
26 |
27 | [ConfigurationProperty("key", DefaultValue = "", IsRequired = true, IsKey = true)]
28 | public string Key
29 | {
30 | get { return (string)this["key"]; }
31 | set { this["key"] = value; }
32 | }
33 |
34 | [ConfigurationProperty("value", DefaultValue = "", IsRequired = true, IsKey = true)]
35 | public string Value
36 | {
37 | get { return (string)this["value"]; }
38 | set { this["value"] = value; }
39 | }
40 | }
41 |
42 |
43 | public class DWSettings : ConfigurationSection
44 | {
45 |
46 | [ConfigurationProperty("ADOWikiParameters", IsDefaultCollection = false)]
47 | [ConfigurationCollection(typeof(ADOWikiParameters),
48 | AddItemName = "add",
49 | ClearItemsName = "clear",
50 | RemoveItemName = "remove")]
51 | public ADOWikiParameters ADOWikiParameters
52 | {
53 | get
54 | {
55 | return (ADOWikiParameters)base["ADOWikiParameters"];
56 | }
57 | }
58 |
59 |
60 | [ConfigurationProperty("Solutions", IsDefaultCollection = false)]
61 | [ConfigurationCollection(typeof(Solutions),
62 | AddItemName = "Solution",
63 | ClearItemsName = "clear",
64 | RemoveItemName = "remove")]
65 | public Solutions Solutions
66 | {
67 | get
68 | {
69 | return (Solutions)base["Solutions"];
70 | }
71 | }
72 |
73 | [ConfigurationProperty("Groups", IsDefaultCollection = false)]
74 | [ConfigurationCollection(typeof(Groups),
75 | AddItemName = "Group",
76 | ClearItemsName = "clear",
77 | RemoveItemName = "remove")]
78 | public Groups Groups
79 | {
80 | get
81 | {
82 | return (Groups)base["Groups"];
83 | }
84 | }
85 |
86 | [ConfigurationProperty("MapConfigs", IsDefaultCollection = false)]
87 | [ConfigurationCollection(typeof(MapConfigs),
88 | AddItemName = "Map",
89 | ClearItemsName = "clear",
90 | RemoveItemName = "remove")]
91 | public MapConfigs MapConfigs
92 | {
93 | get
94 | {
95 | return (MapConfigs)base["MapConfigs"];
96 | }
97 | }
98 | }
99 |
100 | public class ADOWikiParameters : ConfigurationElementCollection
101 | {
102 | public ADOWikiParameters()
103 | {
104 | // Console.WriteLine("ServiceCollection Constructor");
105 | }
106 |
107 | public ADOWikiParameter this[int index]
108 | {
109 | get { return (ADOWikiParameter)BaseGet(index); }
110 | set
111 | {
112 | if (BaseGet(index) != null)
113 | {
114 | BaseRemoveAt(index);
115 | }
116 | BaseAdd(index, value);
117 | }
118 | }
119 |
120 | public void Add(ADOWikiParameter serviceConfig)
121 | {
122 | BaseAdd(serviceConfig);
123 | }
124 |
125 | public void Clear()
126 | {
127 | BaseClear();
128 | }
129 |
130 | protected override ConfigurationElement CreateNewElement()
131 | {
132 | return new ADOWikiParameter();
133 | }
134 |
135 | protected override object GetElementKey(ConfigurationElement element)
136 | {
137 | return ((ADOWikiParameter)element).Key;
138 | }
139 |
140 | public void Remove(ADOWikiParameter serviceConfig)
141 | {
142 | BaseRemove(serviceConfig.Key);
143 | }
144 |
145 | public void RemoveAt(int index)
146 | {
147 | BaseRemoveAt(index);
148 | }
149 |
150 | public void Remove(string name)
151 | {
152 | BaseRemove(name);
153 | }
154 | }
155 |
156 | public class Solutions : ConfigurationElementCollection
157 | {
158 | public Solutions()
159 | {
160 | // Console.WriteLine("ServiceCollection Constructor");
161 | }
162 |
163 | public Solution this[int index]
164 | {
165 | get { return (Solution)BaseGet(index); }
166 | set
167 | {
168 | if (BaseGet(index) != null)
169 | {
170 | BaseRemoveAt(index);
171 | }
172 | BaseAdd(index, value);
173 | }
174 | }
175 |
176 | public void Add(Solution serviceConfig)
177 | {
178 | BaseAdd(serviceConfig);
179 | }
180 |
181 | public void Clear()
182 | {
183 | BaseClear();
184 | }
185 |
186 | protected override ConfigurationElement CreateNewElement()
187 | {
188 | return new Solution();
189 | }
190 |
191 | protected override object GetElementKey(ConfigurationElement element)
192 | {
193 | return ((Solution)element).Name;
194 | }
195 |
196 | public void Remove(Solution serviceConfig)
197 | {
198 | BaseRemove(serviceConfig.Name);
199 | }
200 |
201 | public void RemoveAt(int index)
202 | {
203 | BaseRemoveAt(index);
204 | }
205 |
206 | public void Remove(string name)
207 | {
208 | BaseRemove(name);
209 | }
210 | }
211 |
212 | public class Groups : ConfigurationElementCollection
213 | {
214 | public Groups()
215 | {
216 | //Console.WriteLine("ServiceCollection Constructor");
217 | }
218 |
219 | public Group this[int index]
220 | {
221 | get { return (Group)BaseGet(index); }
222 | set
223 | {
224 | if (BaseGet(index) != null)
225 | {
226 | BaseRemoveAt(index);
227 | }
228 | BaseAdd(index, value);
229 | }
230 | }
231 |
232 | public void Add(Group serviceConfig)
233 | {
234 | BaseAdd(serviceConfig);
235 | }
236 |
237 | public void Clear()
238 | {
239 | BaseClear();
240 | }
241 |
242 | protected override ConfigurationElement CreateNewElement()
243 | {
244 | return new Group();
245 | }
246 |
247 | protected override object GetElementKey(ConfigurationElement element)
248 | {
249 | return ((Group)element).name;
250 | }
251 |
252 | public void Remove(Group serviceConfig)
253 | {
254 | BaseRemove(serviceConfig.name);
255 | }
256 |
257 | public void RemoveAt(int index)
258 | {
259 | BaseRemoveAt(index);
260 | }
261 |
262 | public void Remove(string name)
263 | {
264 | BaseRemove(name);
265 | }
266 | }
267 |
268 |
269 | public class MapConfigs : ConfigurationElementCollection
270 | {
271 | public MapConfigs()
272 | {
273 |
274 | }
275 |
276 | public MapConfig this[int index]
277 | {
278 | get { return (MapConfig)BaseGet(index); }
279 | set
280 | {
281 | if (BaseGet(index) != null)
282 | {
283 | BaseRemoveAt(index);
284 | }
285 | BaseAdd(index, value);
286 | }
287 | }
288 |
289 | public void Add(MapConfig serviceConfig)
290 | {
291 | BaseAdd(serviceConfig);
292 | }
293 |
294 | public void Clear()
295 | {
296 | BaseClear();
297 | }
298 |
299 | protected override ConfigurationElement CreateNewElement()
300 | {
301 | return new MapConfig();
302 | }
303 |
304 | protected override object GetElementKey(ConfigurationElement element)
305 | {
306 | return ((MapConfig)element).mapName;
307 | }
308 |
309 | public void Remove(MapConfig serviceConfig)
310 | {
311 | BaseRemove(serviceConfig.mapName);
312 | }
313 |
314 | public void RemoveAt(int index)
315 | {
316 | BaseRemoveAt(index);
317 | }
318 |
319 | public void Remove(string name)
320 | {
321 | BaseRemove(name);
322 | }
323 |
324 | public static implicit operator List