├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── pull_request_template.md
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Common
├── Common.csproj
├── Contracts
│ ├── ConnectorApiActions.cs
│ ├── ContractEnums.cs
│ ├── DataJobStatus.cs
│ ├── DataJobStatusDetail.cs
│ ├── DataMessage.cs
│ ├── DequeueResponse.cs
│ ├── EntityExecutionStatus.cs
│ ├── PackageApiActions.cs
│ └── SettingsConstants.cs
├── Helpers
│ ├── AuthenticationHelper.cs
│ ├── EncryptDecrypt.cs
│ ├── Extensions.cs
│ ├── FileOperationsHelper.cs
│ ├── HttpClientHelper.cs
│ └── HttpRetryHandler.cs
├── JobSettings
│ ├── DownloadJobSettings.cs
│ ├── ExecutionJobSettings.cs
│ ├── ExportJobSettings.cs
│ ├── ImportJobSettings.cs
│ ├── ProcessingJobSettings.cs
│ ├── Settings.cs
│ └── UploadJobSettings.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
└── app.config
├── Job.Download
├── Download.cs
├── Job.Download.csproj
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── app.config
└── packages.config
├── Job.ExecutionMonitor
├── ExecutionMonitor.cs
├── Job.ExecutionMonitor.csproj
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── app.config
└── packages.config
├── Job.Export
├── Export.cs
├── Job.Export.csproj
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── app.config
└── packages.config
├── Job.Import
├── Import.cs
├── Job.Import.csproj
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── app.config
└── packages.config
├── Job.ProcessingMonitor
├── Job.ProcessingMonitor.csproj
├── ProcessingMonitor.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── app.config
└── packages.config
├── Job.Upload
├── Job.Upload.csproj
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Upload.cs
├── app.config
└── packages.config
├── LICENSE.txt
├── README.md
├── Recurring Integrations Scheduler.sln
├── SECURITY.md
├── Scheduler
├── App.config
├── Assets
│ ├── Add_16xMD.png
│ ├── Edit_16xMD.png
│ ├── Folder open_32xMD_exp.png
│ ├── Recurring Integrations Scheduler.ico
│ ├── Remove_16xMD.png
│ └── ValidateDocument_16x.png
├── Forms
│ ├── AadApplicationForm.Designer.cs
│ ├── AadApplicationForm.cs
│ ├── AadApplicationForm.resx
│ ├── AboutBox.Designer.cs
│ ├── AboutBox.cs
│ ├── AboutBox.resx
│ ├── Connect.Designer.cs
│ ├── Connect.cs
│ ├── Connect.resx
│ ├── CronExamples.Designer.cs
│ ├── CronExamples.cs
│ ├── CronExamples.resx
│ ├── DataJobForm.Designer.cs
│ ├── DataJobForm.cs
│ ├── DataJobForm.resx
│ ├── DownloadJobV3.Designer.cs
│ ├── DownloadJobV3.cs
│ ├── DownloadJobV3.resx
│ ├── ExportJobV3.Designer.cs
│ ├── ExportJobV3.cs
│ ├── ExportJobV3.resx
│ ├── ImportJobV3.Designer.cs
│ ├── ImportJobV3.cs
│ ├── ImportJobV3.resx
│ ├── InstanceForm.Designer.cs
│ ├── InstanceForm.cs
│ ├── InstanceForm.resx
│ ├── JobGroupForm.Designer.cs
│ ├── JobGroupForm.cs
│ ├── JobGroupForm.resx
│ ├── MainForm.Designer.cs
│ ├── MainForm.cs
│ ├── MainForm.resx
│ ├── Parameters.Designer.cs
│ ├── Parameters.cs
│ ├── Parameters.resx
│ ├── UploadJobV3.Designer.cs
│ ├── UploadJobV3.cs
│ ├── UploadJobV3.resx
│ ├── UserForm.Designer.cs
│ ├── UserForm.cs
│ ├── UserForm.resx
│ ├── ValidateConnection.Designer.cs
│ ├── ValidateConnection.cs
│ └── ValidateConnection.resx
├── FormsHelper.cs
├── GlobalSuppressions.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── Scheduler.cs
├── Scheduler.csproj
├── Settings
│ └── Settings.cs
├── app.manifest
└── packages.config
├── Server
├── App.config
├── Configuration.cs
├── IQuartzServer.cs
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
├── QuartzServer.cs
├── QuartzServerFactory.cs
├── Schedule.xml
├── Server.csproj
└── packages.config
├── Setup
├── README.md
├── Recurring Integrations Scheduler.ico
└── Recurring Integrations Scheduler.iss
├── Third Party Notices.txt
└── Version.cs
/.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/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Recurring Integration Scheduler version (please complete the following information):**
27 | - Version [e.g. 22]
28 |
29 | **Dynamics 365 version (please complete the following information):**
30 | - Application version
31 | - Platform version
32 |
33 | **Additional context**
34 | Add any other context about the problem here.
35 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Types of changes
2 |
3 | - [ ] Bug fix (non-breaking change which fixes an issue)
4 | - [ ] New feature (non-breaking change which adds functionality)
5 | - [ ] Breaking change (fix or feature that would cause existing functionality to change)
6 | - [ ] I have read the **CONTRIBUTING** document.
7 | - [ ] My code follows the code style of this project.
8 | - [ ] My change requires a change to the documentation.
9 | - [ ] I have updated the documentation accordingly.
10 | - [ ] I have added tests to cover my changes.
11 | - [ ] All new and existing tests passed.
12 |
--------------------------------------------------------------------------------
/.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 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
290 | # Build artefacts
291 | /.vscode
292 | /Setup/Quartz.Server.exe
293 | /Setup/Topshelf.dll
294 | /Recurring Integrations Scheduler Setup.exe
295 | /Setup/Quartz.Serialization.Json.dll
296 | /Setup/Quartz.Plugins.dll
297 | /Setup/Quartz.Jobs.dll
298 | /Setup/Quartz.dll
299 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 |
2 | [homepage]: http://contributor-covenant.org
3 | [version]: http://contributor-covenant.org/version/1/4/
4 |
5 |
6 | # Microsoft Open Source Code of Conduct
7 | This code of conduct outlines expectations for participation in Microsoft-managed open source communities, as well as steps for reporting unacceptable behavior. We are committed to providing a welcoming and inspiring community for all. People violating this code of conduct may be banned from the community.
8 |
9 | Our open source communities strive to:
10 | * **Be friendly and patient:** Remember you might not be communicating in someone else's primary spoken or programming language, and others may not have your level of understanding.
11 | * **Be welcoming:** Our communities welcome and support people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, color, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
12 | * **Be respectful:** We are a world-wide community of professionals, and we conduct ourselves professionally. Disagreement is no excuse for poor behavior and poor manners. Disrespectful and unacceptable behavior includes, but is not limited to:
13 | * Violent threats or language.
14 | * Discriminatory or derogatory jokes and language.
15 | * Posting sexually explicit or violent material.
16 | * Posting, or threatening to post, people's personally identifying information ("doxing").
17 | * Insults, especially those using discriminatory terms or slurs.
18 | * Behavior that could be perceived as sexual attention.
19 | * Advocating for or encouraging any of the above behaviors.
20 | * **Understand disagreements:** Disagreements, both social and technical, are useful learning opportunities. Seek to understand the other viewpoints and resolve differences constructively.
21 | * This code is not exhaustive or complete. It serves to capture our common understanding of a productive, collaborative environment. We expect the code to be followed in spirit as much as in the letter.
22 | ## Scope
23 | This code of conduct applies to all repos and communities for Microsoft-managed open source projects regardless of whether or not the repo explicitly calls out its use of this code. The code also applies in public spaces when an individual is representing a project or its community. Examples include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
24 |
25 | Note: Some Microsoft-managed communities have codes of conduct that pre-date this document and issue resolution process. While communities are not required to change their code, they are expected to use the resolution process outlined here. The review team will coordinate with the communities involved to address your concerns.
26 | ## Reporting Code of Conduct Issues
27 | We encourage all communities to resolve issues on their own whenever possible. This builds a broader and deeper understanding and ultimately a healthier interaction. In the event that an issue cannot be resolved locally, please feel free to report your concerns by contacting [opencode@microsoft.com](mailto:opencode@microsoft.com). Your report will be handled in accordance with the issue resolution process described in the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/).
28 |
29 | In your report please include:
30 | * Your contact information.
31 | * Names (real, usernames or pseudonyms) of any individuals involved. If there are additional witnesses, please include them as well.
32 | * Your account of what occurred, and if you believe the incident is ongoing. If there is a publicly available record (e.g. a mailing list archive or a public chat log), please include a link or attachment.
33 | * Any additional information that may be helpful.
34 |
35 | All reports will be reviewed by a multi-person team and will result in a response that is deemed necessary and appropriate to the circumstances. Where additional perspectives are needed, the team may seek insight from others with relevant expertise or experience. The confidentiality of the person reporting the incident will be kept at all times. Involved parties are never part of the review team.
36 |
37 | Anyone asked to stop unacceptable behavior is expected to comply immediately. If an individual engages in unacceptable behavior, the review team may take any action they deem appropriate, including a permanent ban from the community.
38 |
39 | _This code of conduct is based on the [template](http://todogroup.org/opencodeofconduct) established by the TODO Group and used by numerous other large communities (e.g., [Facebook](https://code.facebook.com/pages/876921332402685/open-source-code-of-conduct), [Yahoo](https://yahoo.github.io/codeofconduct), [Twitter](https://engineering.twitter.com/opensource/code-of-conduct), [GitHub](http://todogroup.org/opencodeofconduct/#opensource@github.com)) and the Scope section from the [Contributor Covenant version 1.4](http://contributor-covenant.org/version/1/4/)._
40 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing
2 |
3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.
4 |
5 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
6 |
7 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
8 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
9 |
--------------------------------------------------------------------------------
/Common/Common.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {96BB041A-3FDE-400F-ADDA-9DB19F3274BE}
8 | Library
9 | Properties
10 | RecurringIntegrationsScheduler.Common
11 | RecurringIntegrationsScheduler.Common
12 | v4.7.2
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | ..\Output\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 | false
25 | false
26 | 8.0
27 |
28 |
29 | pdbonly
30 | true
31 | ..\Output\Release\
32 | TRACE
33 | prompt
34 | 4
35 | 8.0
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | Version.cs
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 | True
78 | True
79 | Resources.resx
80 |
81 |
82 |
83 |
84 | ResXFileCodeGenerator
85 | Resources.Designer.cs
86 | Designer
87 |
88 |
89 |
90 |
91 | 2.0.13
92 |
93 |
94 | 4.37.0
95 |
96 |
97 | 5.2.9
98 |
99 |
100 | 13.0.1
101 |
102 |
103 | 7.2.2
104 |
105 |
106 | 3.3.3
107 |
108 |
109 | 1.2.14
110 |
111 |
112 | 2.0.0
113 |
114 |
115 |
116 |
123 |
--------------------------------------------------------------------------------
/Common/Contracts/ConnectorApiActions.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | namespace RecurringIntegrationsScheduler.Common.Contracts
5 | {
6 | ///
7 | /// Class holding all requests paths related to Connector API
8 | ///
9 | public static class ConnectorApiActions
10 | {
11 | public const string EnqueuePath = "api/connector/enqueue/";
12 | public const string DequeuePath = "api/connector/dequeue/";
13 | public const string AckPath = "api/connector/ack/";
14 | public const string JobStatusPath = "api/connector/jobstatus/";
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Common/Contracts/ContractEnums.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | namespace RecurringIntegrationsScheduler.Common.Contracts
5 | {
6 | ///
7 | /// Recurring data job state
8 | ///
9 | public enum DataJobState
10 | {
11 | Enqueued = 0,
12 | Dequeued = 1,
13 | Downloaded = 2,
14 | Acked = 3,
15 | InProcess = 4,
16 | Processed = 5,
17 | ProcessedWithErrors = 6,
18 | PostProcessError = 7,
19 | PreProcessError = 8
20 | }
21 |
22 | ///
23 | /// Entity execution status
24 | ///
25 | public enum EntityExecutionStateEnum
26 | {
27 | NotStarted,
28 | Waiting,
29 | Executing,
30 | Error,
31 | Finished,
32 | Ready,
33 | NotRun,
34 | Cancelling,
35 | Canceled,
36 | Hold
37 | }
38 |
39 | ///
40 | /// Message status
41 | ///
42 | public enum MessageStatus
43 | {
44 | Input,
45 | InProcess,
46 | Enqueued,
47 | Failed,
48 | Succeeded
49 | }
50 |
51 | ///
52 | /// Order by options
53 | ///
54 | public enum OrderByOptions
55 | {
56 | Created,
57 | Modified,
58 | FileName,
59 | Size
60 | }
61 |
62 | ///
63 | /// IntegrationActivityMessageStatus
64 | ///
65 | public enum IntegrationActivityMessageStatus
66 | {
67 | Enqueued = 0,
68 | Dequeued = 1,
69 | Downloaded = 2,
70 | Acked = 3,
71 | Processing = 4,
72 | Processed = 5,
73 | ProcessedWithErrors = 6,
74 | PostProcessingError = 7,
75 | PreProcessingError = 8,
76 | PreProcessing = 9
77 | }
78 | }
--------------------------------------------------------------------------------
/Common/Contracts/DataJobStatus.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System;
5 |
6 | namespace RecurringIntegrationsScheduler.Common.Contracts
7 | {
8 | ///
9 | /// Recurring data job status object
10 | ///
11 | public class DataJobStatus
12 | {
13 | ///
14 | /// Gets or sets the data project.
15 | ///
16 | ///
17 | /// The data project.
18 | ///
19 | public string DataProject { get; set; }
20 | ///
21 | /// Gets or sets the data job identifier.
22 | ///
23 | ///
24 | /// The data job identifier.
25 | ///
26 | public string DataJobIdentifier { get; set; }
27 | ///
28 | /// Gets or sets the external identifier.
29 | ///
30 | ///
31 | /// The external identifier.
32 | ///
33 | public string ExternalIdentifier { get; set; }
34 | ///
35 | /// Gets or sets the execution identifier.
36 | ///
37 | ///
38 | /// The execution identifier.
39 | ///
40 | public string ExecutionIdentifier { get; set; }
41 | ///
42 | /// Gets or sets the data job started date time.
43 | ///
44 | ///
45 | /// The data job started date time.
46 | ///
47 | public DateTime DataJobStartedDateTime { get; set; }
48 | ///
49 | /// Gets or sets the data job completed date time.
50 | ///
51 | ///
52 | /// The data job completed date time.
53 | ///
54 | public DateTime DataJobCompletedDateTime { get; set; }
55 | ///
56 | /// Gets or sets the state of the data job.
57 | ///
58 | ///
59 | /// The state of the data job.
60 | ///
61 | public DataJobState DataJobState { get; set; }
62 | }
63 | }
--------------------------------------------------------------------------------
/Common/Contracts/DataJobStatusDetail.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Collections.Generic;
5 |
6 | namespace RecurringIntegrationsScheduler.Common.Contracts
7 | {
8 | ///
9 | /// Recurring data job status detail object
10 | ///
11 | public class DataJobStatusDetail
12 | {
13 | ///
14 | /// The data job status
15 | ///
16 | public DataJobStatus DataJobStatus;
17 |
18 | ///
19 | /// The execution log
20 | ///
21 | public string ExecutionLog;
22 |
23 | ///
24 | /// Gets or sets the execution detail.
25 | ///
26 | ///
27 | /// The execution detail.
28 | ///
29 | public List ExecutionDetail { get; set; }
30 | }
31 | }
--------------------------------------------------------------------------------
/Common/Contracts/DataMessage.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using Newtonsoft.Json;
5 | using Newtonsoft.Json.Converters;
6 |
7 | namespace RecurringIntegrationsScheduler.Common.Contracts
8 | {
9 | ///
10 | /// Contract to abstract the input data file
11 | /// and its processing status (on the client)
12 | ///
13 | public class DataMessage
14 | {
15 | ///
16 | /// Initializes a new instance of the class.
17 | ///
18 | public DataMessage()
19 | {
20 | }
21 |
22 | ///
23 | /// Initiate new dataMessage object based on existing one
24 | ///
25 | ///
26 | public DataMessage(DataMessage dataMessage)
27 | {
28 | Name = dataMessage.Name;
29 | FullPath = dataMessage.FullPath;
30 | MessageId = dataMessage.MessageId;
31 | MessageStatus = dataMessage.MessageStatus;
32 | DataJobState = dataMessage.DataJobState;
33 | CorrelationId = dataMessage.CorrelationId;
34 | PopReceipt = dataMessage.PopReceipt;
35 | DownloadLocation = dataMessage.DownloadLocation;
36 | }
37 |
38 | ///
39 | /// Name.
40 | ///
41 | ///
42 | /// The name.
43 | ///
44 | public string Name { get; set; }
45 |
46 | ///
47 | /// Full path of the message
48 | ///
49 | ///
50 | /// The full path.
51 | ///
52 | public string FullPath { get; set; }
53 |
54 | ///
55 | /// Id of the message in data job queue
56 | ///
57 | ///
58 | /// The message identifier.
59 | ///
60 | public string MessageId { get; set; }
61 |
62 | ///
63 | /// Status
64 | ///
65 | ///
66 | /// The message status.
67 | ///
68 | [JsonConverter(typeof(StringEnumConverter))]
69 | public MessageStatus MessageStatus { get; set; }
70 |
71 | ///
72 | /// Data job state
73 | ///
74 | ///
75 | /// The state of the data job.
76 | ///
77 | [JsonConverter(typeof(StringEnumConverter))]
78 | public DataJobState DataJobState { get; set; }
79 |
80 | ///
81 | /// Gets or sets the correlation identifier.
82 | ///
83 | ///
84 | /// The correlation identifier.
85 | ///
86 | public string CorrelationId { get; set; }
87 |
88 | ///
89 | /// Gets or sets the pop receipt.
90 | ///
91 | ///
92 | /// The pop receipt.
93 | ///
94 | public string PopReceipt { get; set; }
95 |
96 | ///
97 | /// Gets or sets the download location.
98 | ///
99 | ///
100 | /// The download location.
101 | ///
102 | public string DownloadLocation { get; set; }
103 | }
104 | }
--------------------------------------------------------------------------------
/Common/Contracts/DequeueResponse.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | namespace RecurringIntegrationsScheduler.Common.Contracts
5 | {
6 | public class DequeueResponse
7 | {
8 | ///
9 | /// Gets or sets the correlation identifier.
10 | ///
11 | ///
12 | /// The correlation identifier.
13 | ///
14 | public string CorrelationId { get; set; }
15 |
16 | ///
17 | /// Gets or sets the pop receipt.
18 | ///
19 | ///
20 | /// The pop receipt.
21 | ///
22 | public string PopReceipt { get; set; }
23 |
24 | ///
25 | /// Gets or sets the download location.
26 | ///
27 | ///
28 | /// The download location.
29 | ///
30 | public string DownloadLocation { get; set; }
31 |
32 | ///
33 | /// Converter from DataMessage
34 | ///
35 | /// The data message.
36 | ///
37 | /// The result of the conversion.
38 | ///
39 | public static explicit operator DequeueResponse(DataMessage dataMessage)
40 | {
41 | return new DequeueResponse
42 | {
43 | CorrelationId = dataMessage.CorrelationId,
44 | PopReceipt = dataMessage.PopReceipt,
45 | DownloadLocation = dataMessage.DownloadLocation
46 | };
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/Common/Contracts/EntityExecutionStatus.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System;
5 |
6 | namespace RecurringIntegrationsScheduler.Common.Contracts
7 | {
8 | public class EntityExecutionStatus
9 | {
10 | ///
11 | /// Gets or sets the name of the entity.
12 | ///
13 | ///
14 | /// The name of the entity.
15 | ///
16 | public string EntityName { get; set; }
17 | ///
18 | /// Gets or sets the company.
19 | ///
20 | ///
21 | /// The company.
22 | ///
23 | public string Company { get; set; }
24 | ///
25 | /// Gets or sets the staging records.
26 | ///
27 | ///
28 | /// The staging records.
29 | ///
30 | public int StagingRecords { get; set; }
31 | ///
32 | /// Gets or sets the staging status.
33 | ///
34 | ///
35 | /// The staging status.
36 | ///
37 | public EntityExecutionStateEnum StagingStatus { get; set; }
38 | ///
39 | /// Gets or sets the staging error count.
40 | ///
41 | ///
42 | /// The staging error count.
43 | ///
44 | public int StagingErrorCount { get; set; }
45 | ///
46 | /// Gets or sets the target records.
47 | ///
48 | ///
49 | /// The target records.
50 | ///
51 | public int TargetRecords { get; set; }
52 | ///
53 | /// Gets or sets the target status.
54 | ///
55 | ///
56 | /// The target status.
57 | ///
58 | public EntityExecutionStateEnum TargetStatus { get; set; }
59 | ///
60 | /// Gets or sets the target error count.
61 | ///
62 | ///
63 | /// The target error count.
64 | ///
65 | public int TargetErrorCount { get; set; }
66 | ///
67 | /// Gets or sets the execution started date time.
68 | ///
69 | ///
70 | /// The execution started date time.
71 | ///
72 | public DateTime ExecutionStartedDateTime { get; set; }
73 | ///
74 | /// Gets or sets the execution completed date time.
75 | ///
76 | ///
77 | /// The execution completed date time.
78 | ///
79 | public DateTime ExecutionCompletedDateTime { get; set; }
80 | }
81 | }
--------------------------------------------------------------------------------
/Common/Contracts/PackageApiActions.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | namespace RecurringIntegrationsScheduler.Common.Contracts
5 | {
6 | ///
7 | /// Class holding requests paths related to Package API
8 | ///
9 | public static class PackageApiActions
10 | {
11 | public const string GetAzureWriteUrlActionPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.GetAzureWriteUrl";
12 | public const string GetExecutionSummaryStatusActionPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.GetExecutionSummaryStatus";
13 | public const string GetExportedPackageUrlActionPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.GetExportedPackageUrl";
14 | public const string GetExecutionSummaryPageUrlActionPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.GetExecutionSummaryPageUrl";
15 | public const string ImportFromPackageActionPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.ImportFromPackage";
16 | public const string DeleteExecutionHistoryJobActionPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.DeleteExecutionHistoryJob";
17 | public const string ExportToPackageActionPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.ExportToPackage";
18 | public const string ExportFromPackageActionPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.ExportFromPackage";
19 | public const string GetMessageStatusActionPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.GetMessageStatus";
20 | public const string GetImportTargetErrorKeysFileUrlPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.GetImportTargetErrorKeysFileUrl";
21 | public const string GenerateImportTargetErrorKeysFilePath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.GenerateImportTargetErrorKeysFile";
22 | public const string GetExecutionErrorsPath = "data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.GetExecutionErrors";
23 | }
24 | }
--------------------------------------------------------------------------------
/Common/Helpers/AuthenticationHelper.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using Microsoft.Identity.Client;
5 | using Microsoft.IdentityModel.Clients.ActiveDirectory;
6 | using RecurringIntegrationsScheduler.Common.JobSettings;
7 | using System;
8 | using System.Linq;
9 | using System.Security;
10 | using System.Threading.Tasks;
11 | using UrlCombineLib;
12 |
13 | namespace RecurringIntegrationsScheduler.Common.Helpers
14 | {
15 | ///
16 | /// Authentication helper class
17 | ///
18 | internal class AuthenticationHelper
19 | {
20 | private readonly Settings _settings;
21 | private string _authorizationHeader;
22 |
23 | ///
24 | /// Initializes a new instance of the class.
25 | ///
26 | /// Job settings
27 | public AuthenticationHelper(Settings jobSettings)
28 | {
29 | _settings = jobSettings;
30 | }
31 |
32 | ///
33 | /// Authorization result property.
34 | ///
35 | ///
36 | /// Authentication result.
37 | ///
38 | private Microsoft.Identity.Client.AuthenticationResult AuthenticationResult { get; set; }
39 | private Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult AuthenticationResultADAL { get; set; }
40 |
41 | ///
42 | /// Sets authorization header.
43 | ///
44 | /// Authorization header
45 | private async Task AuthorizationHeader()
46 | {
47 | if (!string.IsNullOrEmpty(_authorizationHeader) && (DateTime.UtcNow.AddSeconds(60) < AuthenticationResult.ExpiresOn))
48 | {
49 | return _authorizationHeader;
50 | }
51 | IConfidentialClientApplication appConfidential;
52 | IPublicClientApplication appPublic;
53 | var aosUriAuthUri = new Uri(_settings.AosUri);
54 | string authority = UrlCombine.Combine(_settings.AzureAuthEndpoint, _settings.AadTenant);
55 | string[] scopes = new string[] { UrlCombine.Combine(aosUriAuthUri.AbsoluteUri, ".default") };
56 |
57 | if (_settings.UseServiceAuthentication)
58 | {
59 | appConfidential = ConfidentialClientApplicationBuilder.Create(_settings.AadClientId.ToString())
60 | .WithClientSecret(_settings.AadClientSecret)
61 | .WithAuthority(authority)
62 | .Build();
63 | AuthenticationResult = await appConfidential.AcquireTokenForClient(scopes).ExecuteAsync();
64 | }
65 | else
66 | {
67 | appPublic = PublicClientApplicationBuilder.Create(_settings.AadClientId.ToString())
68 | .WithAuthority(authority)
69 | .Build();
70 | var accounts = await appPublic.GetAccountsAsync();
71 |
72 | if (accounts.Any())
73 | {
74 | AuthenticationResult = await appPublic.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();
75 | }
76 | else
77 | {
78 | using var securePassword = new SecureString();
79 | foreach (char c in _settings.UserPassword)
80 | {
81 | securePassword.AppendChar(c);
82 | }
83 | AuthenticationResult = await appPublic.AcquireTokenByUsernamePassword(scopes, _settings.UserName, securePassword).ExecuteAsync();
84 | }
85 | }
86 | return _authorizationHeader = AuthenticationResult.CreateAuthorizationHeader();
87 | }
88 |
89 | private async Task AuthorizationHeaderADAL()
90 | {
91 | if (!string.IsNullOrEmpty(_authorizationHeader) &&
92 | (DateTime.UtcNow.AddSeconds(60) < AuthenticationResultADAL.ExpiresOn)) return _authorizationHeader;
93 |
94 | var uri = new UriBuilder(_settings.AzureAuthEndpoint)
95 | {
96 | Path = _settings.AadTenant
97 | };
98 |
99 | var aosUriAuthUri = new Uri(_settings.AosUri);
100 | string aosUriAuth = aosUriAuthUri.GetLeftPart(UriPartial.Authority);
101 |
102 | var authenticationContext = new AuthenticationContext(uri.ToString(), validateAuthority: false);
103 |
104 | if (_settings.UseServiceAuthentication)
105 | {
106 | var credentials = new Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential(_settings.AadClientId.ToString(), _settings.AadClientSecret);
107 |
108 | AuthenticationResultADAL = await authenticationContext.AcquireTokenAsync(aosUriAuth, credentials);
109 | }
110 | else
111 | {
112 | var credentials = new UserPasswordCredential(_settings.UserName, _settings.UserPassword);
113 |
114 | AuthenticationResultADAL = await authenticationContext.AcquireTokenAsync(aosUriAuth, _settings.AadClientId.ToString(), credentials);
115 | }
116 |
117 | return _authorizationHeader = AuthenticationResultADAL.CreateAuthorizationHeader();
118 | }
119 |
120 | ///
121 | /// Gets valid authentication header
122 | ///
123 | ///
124 | /// string
125 | ///
126 | public async Task GetValidAuthenticationHeader()
127 | {
128 | if (_settings.UseADAL)
129 | {
130 | _authorizationHeader = await AuthorizationHeaderADAL();
131 | }
132 | else
133 | {
134 | _authorizationHeader = await AuthorizationHeader();
135 | }
136 | return _authorizationHeader;
137 | }
138 | }
139 | }
--------------------------------------------------------------------------------
/Common/Helpers/EncryptDecrypt.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System;
5 | using System.Security.Cryptography;
6 | using System.Text;
7 |
8 | namespace RecurringIntegrationsScheduler.Common.Helpers
9 | {
10 | public static class EncryptDecrypt
11 | {
12 | ///
13 | /// Decrypts a given string.
14 | ///
15 | /// A base64 encoded string that was created
16 | /// through the or
17 | /// extension methods.
18 | ///
19 | /// The decrypted string.
20 | ///
21 | /// If
22 | /// is a null reference.
23 | ///
24 | /// Keep in mind that the decrypted string remains in memory
25 | /// and makes your application vulnerable per se. If runtime protection
26 | /// is essential, should be used.
27 | ///
28 | public static string Decrypt(string cipher)
29 | {
30 | try
31 | {
32 | //parse base64 string
33 | var data = Convert.FromBase64String(cipher);
34 |
35 | //decrypt data
36 | var decrypted = ProtectedData.Unprotect(data, null, DataProtectionScope.LocalMachine);
37 | return Encoding.Unicode.GetString(decrypted);
38 | }
39 | catch
40 | {
41 | return string.Empty;
42 | }
43 | }
44 |
45 | ///
46 | /// Encrypts a given password and returns the encrypted data
47 | /// as a base64 string.
48 | ///
49 | /// An unencrypted string that needs
50 | /// to be secured.
51 | ///
52 | /// A base64 encoded string that represents the encrypted
53 | /// binary data.
54 | ///
55 | /// plainText
56 | /// If
57 | /// is a null reference.
58 | ///
59 | /// This solution is not really secure as we are
60 | /// keeping strings in memory. If runtime protection is essential,
61 | /// should be used.
62 | ///
63 | public static string Encrypt(string plainText)
64 | {
65 | if (plainText == null) throw new ArgumentNullException(nameof(plainText));
66 | try
67 | {
68 | //encrypt data
69 | var data = Encoding.Unicode.GetBytes(plainText);
70 | var encrypted = ProtectedData.Protect(data, null, DataProtectionScope.LocalMachine);
71 |
72 | //return as base64 string
73 | return Convert.ToBase64String(encrypted);
74 | }
75 | catch
76 | {
77 | return string.Empty;
78 | }
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/Common/Helpers/Extensions.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Collections;
5 | using System.Linq;
6 | using System.Linq.Dynamic.Core;
7 |
8 | namespace RecurringIntegrationsScheduler.Common.Helpers
9 | {
10 | public static class Extensions
11 | {
12 | ///
13 | /// Sort extension
14 | ///
15 | /// IEnumerable collection.
16 | /// SortBy keyword
17 | /// order
18 | ///
19 | public static IEnumerable Sort(this IQueryable collection, string sortBy, bool reverse = false)
20 | {
21 | return collection.OrderBy(sortBy + (reverse ? " descending" : ""));
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/Common/Helpers/HttpRetryHandler.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using log4net;
5 | using RecurringIntegrationsScheduler.Common.JobSettings;
6 | using System;
7 | using System.Linq;
8 | using System.Net.Http;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 |
12 | namespace RecurringIntegrationsScheduler.Common.Helpers
13 | {
14 | public class HttpRetryHandler : DelegatingHandler
15 | {
16 | private int _retryAfter;
17 | private readonly Settings _settings;
18 | ///
19 | /// The log
20 | ///
21 | private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
22 |
23 | public HttpRetryHandler(HttpMessageHandler innerHandler, Settings jobSettings)
24 | : base(innerHandler)
25 | {
26 | _settings = jobSettings;
27 | _retryAfter = _settings.RetryDelay;
28 | log4net.Config.XmlConfigurator.Configure();
29 | }
30 |
31 | protected override async Task SendAsync(
32 | HttpRequestMessage request,
33 | CancellationToken cancellationToken)
34 | {
35 | HttpResponseMessage response = null;
36 | for (int i = 0; i < _settings.RetryCount; i++)
37 | {
38 | response = await base.SendAsync(request, cancellationToken);
39 | if (response.IsSuccessStatusCode)
40 | {
41 | return response;
42 | }
43 | if ((int)response.StatusCode == 429)
44 | {
45 |
46 | i--; //Explicit ask for retry. Try until successful
47 | if (response.Headers.Contains("Retry-After"))
48 | {
49 | _retryAfter = int.Parse(response.Headers.GetValues("Retry-After").FirstOrDefault());
50 | Log.Warn($@"Job: {_settings.JobKey}. HttpRetryHandler.Task is being called.
51 | ReqeuestUri: {request.RequestUri}
52 | Response Status Code: {response.StatusCode}
53 | Priority-based throttling in action.
54 | Requested delay (in seconds) between next request: {_retryAfter}");
55 | }
56 | }
57 | if (_retryAfter > 0 && _settings.RetryCount > 1)
58 | {
59 | Log.Warn($@"Job: {_settings.JobKey}. HttpRetryHandler.Task is being called.
60 | Delaying next request for {_retryAfter} seconds...");
61 | Thread.Sleep(TimeSpan.FromSeconds(_retryAfter));
62 | }
63 | }
64 | return response;
65 | }
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/Common/JobSettings/DownloadJobSettings.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using Quartz;
5 | using RecurringIntegrationsScheduler.Common.Contracts;
6 | using RecurringIntegrationsScheduler.Common.Properties;
7 | using System;
8 | using System.Globalization;
9 | using System.IO;
10 |
11 | namespace RecurringIntegrationsScheduler.Common.JobSettings
12 |
13 | {
14 | ///
15 | ///
16 | /// Serialize/deserialize download job settings
17 | ///
18 | ///
19 | public class DownloadJobSettings : Settings
20 | {
21 | ///
22 | /// Initialize and verify settings for job
23 | ///
24 | /// The context.
25 | ///
26 | ///
27 | public override void Initialize(IJobExecutionContext context)
28 | {
29 | var dataMap = context.JobDetail.JobDataMap;
30 |
31 | base.Initialize(context);
32 |
33 | var activityIdStr = dataMap.GetString(SettingsConstants.ActivityId);
34 | if (!Guid.TryParse(activityIdStr, out Guid activityIdGuid) || (Guid.Empty == activityIdGuid))
35 | {
36 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Activity_Id_of_recurring_job_is_missing_or_is_not_a_GUID_in_job_configuration));
37 | }
38 | ActivityId = activityIdGuid;
39 |
40 | DownloadSuccessDir = dataMap.GetString(SettingsConstants.DownloadSuccessDir);
41 | if (!string.IsNullOrEmpty(DownloadSuccessDir))
42 | {
43 | try
44 | {
45 | Directory.CreateDirectory(DownloadSuccessDir);
46 | }
47 | catch (Exception ex)
48 | {
49 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Download_success_directory_does_not_exist_or_cannot_be_accessed), ex);
50 | }
51 | }
52 | else
53 | {
54 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Download_success_directory_is_missing_in_job_configuration));
55 | }
56 |
57 | DownloadErrorsDir = dataMap.GetString(SettingsConstants.DownloadErrorsDir);
58 | if (!string.IsNullOrEmpty(DownloadErrorsDir))
59 | {
60 | try
61 | {
62 | Directory.CreateDirectory(DownloadErrorsDir);
63 | }
64 | catch (Exception ex)
65 | {
66 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Download_errors_directory_does_not_exist_or_cannot_be_accessed), ex);
67 | }
68 | }
69 | else
70 | {
71 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Download_errors_directory_is_missing_in_job_configuration));
72 | }
73 |
74 | UnzipPackage = dataMap.GetBooleanValue(SettingsConstants.UnzipPackage);
75 |
76 | AddTimestamp = dataMap.GetBooleanValue(SettingsConstants.AddTimestamp);
77 |
78 | DeletePackage = dataMap.GetBooleanValue(SettingsConstants.DeletePackage);
79 | }
80 |
81 | #region Members
82 |
83 | ///
84 | /// Gets or sets the activity identifier.
85 | ///
86 | ///
87 | /// The activity identifier.
88 | ///
89 | public Guid ActivityId { get; set; }
90 |
91 | ///
92 | /// Gets the download success dir.
93 | ///
94 | ///
95 | /// The download success dir.
96 | ///
97 | public string DownloadSuccessDir { get; private set; }
98 |
99 | ///
100 | /// Gets the download errors dir.
101 | ///
102 | ///
103 | /// The download errors dir.
104 | ///
105 | public string DownloadErrorsDir { get; private set; }
106 |
107 | ///
108 | /// Gets a value indicating whether [unzip package].
109 | ///
110 | ///
111 | /// true if [unzip package]; otherwise, false.
112 | ///
113 | public bool UnzipPackage { get; private set; }
114 |
115 | ///
116 | /// Gets a value indicating whether [add timestamp].
117 | ///
118 | ///
119 | /// true if [add timestamp]; otherwise, false.
120 | ///
121 | public bool AddTimestamp { get; private set; }
122 |
123 | ///
124 | /// Gets a value indicating whether [delete package].
125 | ///
126 | ///
127 | /// true if [delete package]; otherwise, false.
128 | ///
129 | public bool DeletePackage { get; private set; }
130 |
131 | #endregion
132 | }
133 | }
--------------------------------------------------------------------------------
/Common/JobSettings/ExecutionJobSettings.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using Quartz;
5 | using RecurringIntegrationsScheduler.Common.Contracts;
6 | using RecurringIntegrationsScheduler.Common.Properties;
7 | using System;
8 | using System.Globalization;
9 | using System.IO;
10 |
11 | namespace RecurringIntegrationsScheduler.Common.JobSettings
12 | {
13 | ///
14 | /// Serialize/deserialize execution monitor job settings
15 | ///
16 | ///
17 | public class ExecutionJobSettings : Settings
18 | {
19 | ///
20 | /// Initialize and verify settings for job
21 | ///
22 | /// The context.
23 | ///
24 | ///
25 | public override void Initialize(IJobExecutionContext context)
26 | {
27 | var dataMap = context.JobDetail.JobDataMap;
28 |
29 | base.Initialize(context);
30 |
31 | UploadSuccessDir = dataMap.GetString(SettingsConstants.UploadSuccessDir);
32 | if (!string.IsNullOrEmpty(UploadSuccessDir))
33 | {
34 | try
35 | {
36 | Directory.CreateDirectory(UploadSuccessDir);
37 | }
38 | catch (Exception ex)
39 | {
40 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Upload_success_directory_does_not_exist_or_cannot_be_accessed), ex);
41 | }
42 | }
43 | else
44 | {
45 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Upload_success_directory_is_missing_in_job_configuration));
46 | }
47 |
48 | ProcessingSuccessDir = dataMap.GetString(SettingsConstants.ProcessingSuccessDir);
49 | if (!string.IsNullOrEmpty(ProcessingSuccessDir))
50 | {
51 | try
52 | {
53 | Directory.CreateDirectory(ProcessingSuccessDir);
54 | }
55 | catch (Exception ex)
56 | {
57 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Processing_success_directory_does_not_exist_or_cannot_be_accessed), ex);
58 | }
59 | }
60 | else
61 | {
62 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Processing_success_directory_is_missing_in_job_configuration));
63 | }
64 |
65 | ProcessingErrorsDir = dataMap.GetString(SettingsConstants.ProcessingErrorsDir);
66 | if (!string.IsNullOrEmpty(ProcessingErrorsDir))
67 | {
68 | try
69 | {
70 | Directory.CreateDirectory(ProcessingErrorsDir);
71 | }
72 | catch (Exception ex)
73 | {
74 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Processing_errors_directory_does_not_exist_or_cannot_be_accessed), ex);
75 | }
76 | }
77 | else
78 | {
79 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Processing_errors_directory_is_missing_in_job_configuration));
80 | }
81 |
82 | StatusFileExtension = dataMap.GetString("StatusFileExtension");
83 | if (string.IsNullOrEmpty(StatusFileExtension))
84 | {
85 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Extension_of_status_files_is_missing_in_job_configuration));
86 | }
87 |
88 | GetImportTargetErrorKeysFile = dataMap.GetBooleanValue(SettingsConstants.GetImportTargetErrorKeysFile);
89 |
90 | PackageTemplate = dataMap.GetString(SettingsConstants.PackageTemplate);
91 |
92 | DelayBetweenStatusCheck = dataMap.GetInt(SettingsConstants.DelayBetweenStatusCheck);
93 | }
94 |
95 | #region Members
96 |
97 | ///
98 | /// Gets the upload success dir.
99 | ///
100 | ///
101 | /// The upload success dir.
102 | ///
103 | public string UploadSuccessDir { get; private set; }
104 |
105 | ///
106 | /// Gets the processing success dir.
107 | ///
108 | ///
109 | /// The processing success dir.
110 | ///
111 | public string ProcessingSuccessDir { get; private set; }
112 |
113 | ///
114 | /// Gets the processing errors dir.
115 | ///
116 | ///
117 | /// The processing errors dir.
118 | ///
119 | public string ProcessingErrorsDir { get; private set; }
120 |
121 | ///
122 | /// Gets the status file extension.
123 | ///
124 | ///
125 | /// The status file extension.
126 | ///
127 | public string StatusFileExtension { get; private set; }
128 |
129 | ///
130 | /// Gets a value indicating whether to download [error keys file].
131 | ///
132 | ///
133 | /// true if [GetImportTargetErrorKeysFile] is set otherwise, false.
134 | ///
135 | public bool GetImportTargetErrorKeysFile { get; private set; }
136 |
137 | ///
138 | /// Package template location.
139 | ///
140 | ///
141 | /// Package template location.
142 | ///
143 | public string PackageTemplate { get; private set; }
144 |
145 | ///
146 | /// Gets or sets delay between status check.
147 | ///
148 | ///
149 | /// Delay between status checks.
150 | ///
151 | public int DelayBetweenStatusCheck { get; private set; }
152 |
153 | #endregion
154 | }
155 | }
--------------------------------------------------------------------------------
/Common/JobSettings/ExportJobSettings.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using Quartz;
5 | using RecurringIntegrationsScheduler.Common.Contracts;
6 | using RecurringIntegrationsScheduler.Common.Properties;
7 | using System;
8 | using System.Globalization;
9 | using System.IO;
10 |
11 | namespace RecurringIntegrationsScheduler.Common.JobSettings
12 | {
13 | ///
14 | /// Serialize/deserialize download job settings
15 | ///
16 | ///
17 | public class ExportJobSettings : Settings
18 | {
19 | ///
20 | /// Initialize and verify settings for job
21 | ///
22 | /// The context.
23 | ///
24 | ///
25 | public override void Initialize(IJobExecutionContext context)
26 | {
27 | var dataMap = context.JobDetail.JobDataMap;
28 |
29 | base.Initialize(context);
30 |
31 | DownloadSuccessDir = dataMap.GetString(SettingsConstants.DownloadSuccessDir);
32 | if (!string.IsNullOrEmpty(DownloadSuccessDir))
33 | {
34 | try
35 | {
36 | Directory.CreateDirectory(DownloadSuccessDir);
37 | }
38 | catch (Exception ex)
39 | {
40 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Download_success_directory_does_not_exist_or_cannot_be_accessed), ex);
41 | }
42 | }
43 | else
44 | {
45 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Download_success_directory_is_missing_in_job_configuration));
46 | }
47 |
48 | DownloadErrorsDir = dataMap.GetString(SettingsConstants.DownloadErrorsDir);
49 | if (!string.IsNullOrEmpty(DownloadErrorsDir))
50 | {
51 | try
52 | {
53 | Directory.CreateDirectory(DownloadErrorsDir);
54 | }
55 | catch (Exception ex)
56 | {
57 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Download_errors_directory_does_not_exist_or_cannot_be_accessed), ex);
58 | }
59 | }
60 | else
61 | {
62 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Download_errors_directory_is_missing_in_job_configuration));
63 | }
64 |
65 | UnzipPackage = dataMap.GetBooleanValue(SettingsConstants.UnzipPackage);
66 |
67 | AddTimestamp = dataMap.GetBooleanValue(SettingsConstants.AddTimestamp);
68 |
69 | DeletePackage = dataMap.GetBooleanValue(SettingsConstants.DeletePackage);
70 |
71 | DataProject = dataMap.GetString(SettingsConstants.DataProject);
72 |
73 | if (string.IsNullOrEmpty(DataProject))
74 | {
75 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Data_project_is_missing_in_job_configuration));
76 | }
77 |
78 | Company = dataMap.GetString(SettingsConstants.Company);
79 |
80 | if (string.IsNullOrEmpty(Company))
81 | {
82 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Company_is_missing_in_job_configuration));
83 | }
84 |
85 | DelayBetweenStatusCheck = dataMap.GetInt(SettingsConstants.DelayBetweenStatusCheck);
86 | }
87 |
88 | #region Members
89 |
90 | ///
91 | /// Gets the download success dir.
92 | ///
93 | ///
94 | /// The download success dir.
95 | ///
96 | public string DownloadSuccessDir { get; private set; }
97 |
98 | ///
99 | /// Gets the download errors dir.
100 | ///
101 | ///
102 | /// The download errors dir.
103 | ///
104 | public string DownloadErrorsDir { get; private set; }
105 |
106 | ///
107 | /// Gets a value indicating whether [unzip package].
108 | ///
109 | ///
110 | /// true if [unzip package]; otherwise, false.
111 | ///
112 | public bool UnzipPackage { get; private set; }
113 |
114 | ///
115 | /// Gets a value indicating whether [add timestamp].
116 | ///
117 | ///
118 | /// true if [add timestamp]; otherwise, false.
119 | ///
120 | public bool AddTimestamp { get; private set; }
121 |
122 | ///
123 | /// Gets a value indicating whether [delete package].
124 | ///
125 | ///
126 | /// true if [delete package]; otherwise, false.
127 | ///
128 | public bool DeletePackage { get; private set; }
129 |
130 | ///
131 | /// Gets data project.
132 | ///
133 | ///
134 | /// Data project.
135 | ///
136 | public string DataProject { get; private set; }
137 |
138 | ///
139 | /// Gets legal entity id.
140 | ///
141 | ///
142 | /// Legal entity id.
143 | ///
144 | public string Company { get; private set; }
145 |
146 | ///
147 | /// Gets or sets delay between status check.
148 | ///
149 | ///
150 | /// Delay between status checks.
151 | ///
152 | public int DelayBetweenStatusCheck { get; private set; }
153 |
154 | #endregion
155 | }
156 | }
--------------------------------------------------------------------------------
/Common/JobSettings/ProcessingJobSettings.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using Quartz;
5 | using RecurringIntegrationsScheduler.Common.Contracts;
6 | using RecurringIntegrationsScheduler.Common.Properties;
7 | using System;
8 | using System.Globalization;
9 | using System.IO;
10 |
11 | namespace RecurringIntegrationsScheduler.Common.JobSettings
12 | {
13 | ///
14 | /// Serialize/deserialize processing job settings
15 | ///
16 | ///
17 | public class ProcessingJobSettings : Settings
18 | {
19 | ///
20 | /// Initialize and verify settings for job
21 | ///
22 | /// The context.
23 | ///
24 | ///
25 | public override void Initialize(IJobExecutionContext context)
26 | {
27 | var dataMap = context.JobDetail.JobDataMap;
28 |
29 | base.Initialize(context);
30 |
31 | var activityIdStr = dataMap.GetString(SettingsConstants.ActivityId);
32 | if (!Guid.TryParse(activityIdStr, out Guid activityIdGuid) || (Guid.Empty == activityIdGuid))
33 | {
34 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Activity_Id_of_recurring_job_is_missing_or_is_not_a_GUID_in_job_configuration));
35 | }
36 |
37 | ActivityId = activityIdGuid;
38 |
39 | UploadSuccessDir = dataMap.GetString(SettingsConstants.UploadSuccessDir);
40 | if (!string.IsNullOrEmpty(UploadSuccessDir))
41 | {
42 | try
43 | {
44 | Directory.CreateDirectory(UploadSuccessDir);
45 | }
46 | catch (Exception ex)
47 | {
48 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Upload_success_directory_does_not_exist_or_cannot_be_accessed), ex);
49 | }
50 | }
51 | else
52 | {
53 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Upload_success_directory_is_missing_in_job_configuration));
54 | }
55 |
56 | ProcessingSuccessDir = dataMap.GetString(SettingsConstants.ProcessingSuccessDir);
57 | if (!string.IsNullOrEmpty(ProcessingSuccessDir))
58 | {
59 | try
60 | {
61 | Directory.CreateDirectory(ProcessingSuccessDir);
62 | }
63 | catch (Exception ex)
64 | {
65 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Processing_success_directory_does_not_exist_or_cannot_be_accessed), ex);
66 | }
67 | }
68 | else
69 | {
70 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Processing_success_directory_is_missing_in_job_configuration));
71 | }
72 |
73 | ProcessingErrorsDir = dataMap.GetString(SettingsConstants.ProcessingErrorsDir);
74 | if (!string.IsNullOrEmpty(ProcessingErrorsDir))
75 | {
76 | try
77 | {
78 | Directory.CreateDirectory(ProcessingErrorsDir);
79 | }
80 | catch (Exception ex)
81 | {
82 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Processing_errors_directory_does_not_exist_or_cannot_be_accessed), ex);
83 | }
84 | }
85 | else
86 | {
87 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Processing_errors_directory_is_missing_in_job_configuration));
88 | }
89 |
90 | StatusFileExtension = dataMap.GetString("StatusFileExtension");
91 | if (string.IsNullOrEmpty(StatusFileExtension))
92 | {
93 | throw new JobExecutionException(string.Format(CultureInfo.InvariantCulture, Resources.Extension_of_status_files_is_missing_in_job_configuration));
94 | }
95 |
96 | StatusCheckInterval = dataMap.GetInt(SettingsConstants.DelayBetweenStatusCheck);
97 | }
98 |
99 | #region Members
100 |
101 | ///
102 | /// Gets or sets the activity identifier.
103 | ///
104 | ///
105 | /// The activity identifier.
106 | ///
107 | public Guid ActivityId { get; private set; }
108 |
109 | ///
110 | /// Gets the upload success dir.
111 | ///
112 | ///
113 | /// The upload success dir.
114 | ///
115 | public string UploadSuccessDir { get; private set; }
116 |
117 | ///
118 | /// Gets the processing success dir.
119 | ///
120 | ///
121 | /// The processing success dir.
122 | ///
123 | public string ProcessingSuccessDir { get; private set; }
124 |
125 | ///
126 | /// Gets the processing errors dir.
127 | ///
128 | ///
129 | /// The processing errors dir.
130 | ///
131 | public string ProcessingErrorsDir { get; private set; }
132 |
133 | ///
134 | /// Gets the status file extension.
135 | ///
136 | ///
137 | /// The status file extension.
138 | ///
139 | public string StatusFileExtension { get; private set; }
140 |
141 | ///
142 | /// Gets or sets delay between status check.
143 | ///
144 | ///
145 | /// Delay between status checks.
146 | ///
147 | public int StatusCheckInterval { get; private set; }
148 |
149 | #endregion
150 | }
151 | }
--------------------------------------------------------------------------------
/Common/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Recurring Integrations Scheduler Common Library")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Recurring Integrations Scheduler")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 |
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 |
27 | [assembly: Guid("96bb041a-3fde-400f-adda-9db19f3274be")]
--------------------------------------------------------------------------------
/Common/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Job.Download/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Recurring Integrations Scheduler Download Job")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Recurring Integrations Scheduler")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 |
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 |
27 | [assembly: Guid("F4692D5C-4C53-4C30-9992-51F98717861D")]
--------------------------------------------------------------------------------
/Job.Download/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Job.Download/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Job.ExecutionMonitor/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Recurring Integrations Scheduler Execution Monitor Job")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Recurring Integrations Scheduler")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 |
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 |
27 | [assembly: Guid("A46268F5-E858-45F1-9E77-C27D4DA6A626")]
--------------------------------------------------------------------------------
/Job.ExecutionMonitor/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Job.ExecutionMonitor/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Job.Export/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Recurring Integrations Scheduler Export Job")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Recurring Integrations Scheduler")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 |
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 |
27 | [assembly: Guid("4B0FEF07-196B-47ED-A3DF-49327D9B4A73")]
--------------------------------------------------------------------------------
/Job.Export/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Job.Export/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Job.Import/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Recurring Integrations Scheduler Import Job")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Recurring Integrations Scheduler")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 |
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 |
27 | [assembly: Guid("0C62174A-DCE9-42A7-8377-2A4C3C8F6E1C")]
--------------------------------------------------------------------------------
/Job.Import/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Job.Import/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Job.ProcessingMonitor/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Recurring Integrations Scheduler Processing Monitor Job")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Recurring Integrations Scheduler")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 |
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 |
27 | [assembly: Guid("4DC46474-B920-4D13-AFC2-5CF1D9B815AA")]
--------------------------------------------------------------------------------
/Job.ProcessingMonitor/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Job.ProcessingMonitor/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Job.Upload/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Recurring Integrations Scheduler Upload Job")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Recurring Integrations Scheduler")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 |
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 |
27 | [assembly: Guid("8BC9E0C9-4E2E-4109-BD51-1E79BF548EAA")]
--------------------------------------------------------------------------------
/Job.Upload/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Job.Upload/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Recurring Integrations Scheduler
2 | Copyright (c) Microsoft Corporation. All rights reserved.
3 |
4 | MIT License
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | THE SOFTWARE
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Recurring Integrations Scheduler RIS
2 |
3 | This tool helps to quickly set up and orchestrate file based integration scenarios to and from Dynamics 365 Finance and Dynamics 365 Supply Chain Management. We see this tool to be a good implementation accelerator for use during the implementation phase of the project for data migration, ad hoc file integration needs and to be used as a proof of concept validator among others.
4 |
5 | ## Recurring Integrations Scheduler Service
6 |
7 | Recurring Integrations Scheduler Service is a Windows service that can trigger many integration jobs at predefined schedule. You can schedule jobs and set their recurrence in a very similar way to well-known D365FO batch framework.
8 |
9 | There are six types of integration jobs you can use: [Import](https://github.com/microsoft/Recurring-Integrations-Scheduler/wiki#import-job), [Export](https://github.com/microsoft/Recurring-Integrations-Scheduler/wiki#export-job) and [Execution monitor](https://github.com/microsoft/Recurring-Integrations-Scheduler/wiki#execution-monitor-job) as well as [Upload](https://github.com/microsoft/Recurring-Integrations-Scheduler/wiki#upload-job), [Download](https://github.com/microsoft/Recurring-Integrations-Scheduler/wiki#download-job) and [Processing monitor](https://github.com/microsoft/Recurring-Integrations-Scheduler/wiki#processing-monitor-job). First three use [Data management package REST API](https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/data-management-api). Three other use [Recurring Integrations REST API](https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/recurring-integrations) and recurring data jobs.
10 | More details in wiki.
11 |
12 | Single Recurring Integrations Scheduler service can work with multiple D365FO instances even within different tenants. This enables both production and implementation scenarios where you need to work with multiple non-prod instances. Recurring Integrations Scheduler logs important events to Windows Event Log. It is possible to increase its logging level to log every step for debugging purposes and to trace possible problems.
13 |
14 | ## Recurring Integrations Scheduler App
15 |
16 | Recurring Integrations Scheduler App is a win32 application that can be used as a configuration front-end for Recurring Integrations Scheduler service or as a completely independent, interactive application used to upload or download files to and from Dynamics 365 Finance or SCM without Recurring Integrations Scheduler Service.
17 | It is possible thanks to internal, private scheduler embedded in Recurring Integrations Scheduler App that works exactly the same way as the Scheduler Service does with one difference - it will stop working once the App is closed.
18 |
19 | ## Installation and configuration
20 |
21 | Please check https://github.com/Microsoft/Recurring-Integrations-Scheduler/wiki
22 |
23 | ## Support
24 |
25 | RIS is not officially supported by Microsoft. Please log an issue here on Github if you encounter a bug in RIS.
26 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/Scheduler/Assets/Add_16xMD.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/Recurring-Integrations-Scheduler/b6f09b6671e46490e3b5fcd192ce1ae4cc6593a5/Scheduler/Assets/Add_16xMD.png
--------------------------------------------------------------------------------
/Scheduler/Assets/Edit_16xMD.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/Recurring-Integrations-Scheduler/b6f09b6671e46490e3b5fcd192ce1ae4cc6593a5/Scheduler/Assets/Edit_16xMD.png
--------------------------------------------------------------------------------
/Scheduler/Assets/Folder open_32xMD_exp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/Recurring-Integrations-Scheduler/b6f09b6671e46490e3b5fcd192ce1ae4cc6593a5/Scheduler/Assets/Folder open_32xMD_exp.png
--------------------------------------------------------------------------------
/Scheduler/Assets/Recurring Integrations Scheduler.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/Recurring-Integrations-Scheduler/b6f09b6671e46490e3b5fcd192ce1ae4cc6593a5/Scheduler/Assets/Recurring Integrations Scheduler.ico
--------------------------------------------------------------------------------
/Scheduler/Assets/Remove_16xMD.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/Recurring-Integrations-Scheduler/b6f09b6671e46490e3b5fcd192ce1ae4cc6593a5/Scheduler/Assets/Remove_16xMD.png
--------------------------------------------------------------------------------
/Scheduler/Assets/ValidateDocument_16x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/Recurring-Integrations-Scheduler/b6f09b6671e46490e3b5fcd192ce1ae4cc6593a5/Scheduler/Assets/ValidateDocument_16x.png
--------------------------------------------------------------------------------
/Scheduler/Forms/AadApplicationForm.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using RecurringIntegrationsScheduler.Properties;
5 | using RecurringIntegrationsScheduler.Settings;
6 | using System;
7 | using System.Text;
8 | using System.Windows.Forms;
9 |
10 | namespace RecurringIntegrationsScheduler.Forms
11 | {
12 | public partial class AadApplicationForm : Form
13 | {
14 | public AadApplicationForm()
15 | {
16 | InitializeComponent();
17 | }
18 |
19 | public AadApplication AadApplication { get; set; }
20 |
21 | private void DataJobForm_Load(object sender, EventArgs e)
22 | {
23 | comboBox1.DataSource = Enum.GetValues(typeof(AuthenticationType));
24 |
25 | if (AadApplication != null)
26 | {
27 | Text = Resources.Edit_Azure_AD_application;
28 | textBox1.Text = AadApplication.Name;
29 | textBox2.Text = AadApplication.ClientId;
30 | textBox3.Text = AadApplication.Secret;
31 | comboBox1.SelectedItem = AadApplication.AuthenticationType;
32 | }
33 | else
34 | {
35 | Text = Resources.Add_Azure_AD_application;
36 | }
37 | }
38 |
39 | private bool InputIsValid()
40 | {
41 | var message = new StringBuilder();
42 |
43 | if (string.IsNullOrEmpty(textBox1.Text))
44 | message.AppendLine(Resources.Friendly_name_is_required);
45 | if (string.IsNullOrEmpty(textBox2.Text))
46 | {
47 | message.AppendLine(Resources.Client_Id_is_required);
48 | }
49 | else
50 | {
51 | var isValid = Guid.TryParse(textBox2.Text, out var guidOutput);
52 | if (!isValid)
53 | message.AppendLine(Resources.Client_Id_is_invalid);
54 | }
55 | if (((AuthenticationType) comboBox1.SelectedItem == AuthenticationType.Service) &&
56 | string.IsNullOrEmpty(textBox3.Text))
57 | message.AppendLine(Resources.Client_secret_is_required);
58 |
59 | if (message.Length > 0)
60 | MessageBox.Show(message.ToString(), Resources.Validation_error, MessageBoxButtons.OK,
61 | MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
62 | return message.Length == 0;
63 | }
64 |
65 | private void ButtonOK_Click(object sender, EventArgs e)
66 | {
67 | if (InputIsValid())
68 | AadApplication = new AadApplication
69 | {
70 | Name = textBox1.Text,
71 | ClientId = textBox2.Text,
72 | Secret = textBox3.Text,
73 | AuthenticationType = (AuthenticationType) comboBox1.SelectedItem
74 | };
75 | else
76 | DialogResult = DialogResult.None;
77 | }
78 |
79 | private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
80 | {
81 | textBox3.Enabled = (AuthenticationType) comboBox1.SelectedItem == AuthenticationType.Service;
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/AadApplicationForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/Scheduler/Forms/AboutBox.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using RecurringIntegrationsScheduler.Properties;
5 | using System.IO;
6 | using System.Reflection;
7 | using System.Windows.Forms;
8 |
9 | namespace RecurringIntegrationsScheduler.Forms
10 | {
11 | internal sealed partial class AboutBox : Form
12 | {
13 | public AboutBox()
14 | {
15 | InitializeComponent();
16 | Text = string.Format(Resources.About_0, AssemblyTitle);
17 | labelProductName.Text = AssemblyProduct;
18 | labelVersion.Text = string.Format(Resources.Version_0, AssemblyVersion);
19 | }
20 |
21 | #region Assembly Attribute Accessors
22 |
23 | private static string AssemblyTitle
24 | {
25 | get
26 | {
27 | var attributes = Assembly.GetExecutingAssembly()
28 | .GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
29 | if (attributes.Length > 0)
30 | {
31 | var titleAttribute = (AssemblyTitleAttribute) attributes[0];
32 | if (titleAttribute.Title != "")
33 | return titleAttribute.Title;
34 | }
35 | return Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
36 | }
37 | }
38 |
39 | private static string AssemblyVersion => Assembly.GetExecutingAssembly().GetName().Version.ToString();
40 |
41 | private static string AssemblyProduct
42 | {
43 | get
44 | {
45 | var attributes = Assembly.GetExecutingAssembly()
46 | .GetCustomAttributes(typeof(AssemblyProductAttribute), false);
47 | return attributes.Length == 0 ? "" : ((AssemblyProductAttribute) attributes[0]).Product;
48 | }
49 | }
50 |
51 | #endregion
52 | }
53 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/Connect.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System;
5 | using System.Windows.Forms;
6 |
7 | namespace RecurringIntegrationsScheduler.Forms
8 | {
9 | public partial class Connect : Form
10 | {
11 | public Connect()
12 | {
13 | InitializeComponent();
14 | }
15 |
16 | public string Server { get; private set; }
17 | public int Port { get; private set; }
18 | public string Scheduler { get; private set; }
19 | public bool Cancelled { get; private set; }
20 |
21 | private void CancelButton_Click(object sender, EventArgs e)
22 | {
23 | Close();
24 | }
25 |
26 | private void ConnectButton_Click(object sender, EventArgs e)
27 | {
28 | Cancelled = false;
29 | Server = serverTextBox.Text;
30 | Port = int.Parse(portTextBox.Text);
31 | Scheduler = schedulerTextBox.Text;
32 | Close();
33 | }
34 |
35 | private void ServerConnectForm_Load(object sender, EventArgs e)
36 | {
37 | Cancelled = true;
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/Connect.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/Scheduler/Forms/CronExamples.Designer.cs:
--------------------------------------------------------------------------------
1 | using RecurringIntegrationsScheduler.Properties;
2 |
3 | namespace RecurringIntegrationsScheduler.Forms
4 | {
5 | partial class CronExamples
6 | {
7 | ///
8 | /// Required designer variable.
9 | ///
10 | private System.ComponentModel.IContainer components = null;
11 |
12 | ///
13 | /// Clean up any resources being used.
14 | ///
15 | /// true if managed resources should be disposed; otherwise, false.
16 | protected override void Dispose(bool disposing)
17 | {
18 | if (disposing && (components != null))
19 | {
20 | components.Dispose();
21 | }
22 | base.Dispose(disposing);
23 | }
24 |
25 | #region Windows Form Designer generated code
26 |
27 | ///
28 | /// Required method for Designer support - do not modify
29 | /// the contents of this method with the code editor.
30 | ///
31 | private void InitializeComponent()
32 | {
33 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CronExamples));
34 | this.textBox1 = new System.Windows.Forms.TextBox();
35 | this.SuspendLayout();
36 | //
37 | // textBox1
38 | //
39 | this.textBox1.Dock = System.Windows.Forms.DockStyle.Fill;
40 | this.textBox1.Font = new System.Drawing.Font("Courier New", 8.142858F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
41 | this.textBox1.Location = new System.Drawing.Point(0, 0);
42 | this.textBox1.Margin = new System.Windows.Forms.Padding(7, 6, 7, 6);
43 | this.textBox1.Multiline = true;
44 | this.textBox1.Name = "textBox1";
45 | this.textBox1.ReadOnly = true;
46 | this.textBox1.Size = new System.Drawing.Size(1544, 541);
47 | this.textBox1.TabIndex = 0;
48 | this.textBox1.Text = resources.GetString("textBox1.Text");
49 | //
50 | // CronExamples
51 | //
52 | this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F);
53 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
54 | this.AutoScroll = true;
55 | this.ClientSize = new System.Drawing.Size(1544, 541);
56 | this.Controls.Add(this.textBox1);
57 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
58 | this.Margin = new System.Windows.Forms.Padding(7, 6, 7, 6);
59 | this.MaximizeBox = false;
60 | this.MaximumSize = new System.Drawing.Size(1570, 612);
61 | this.MinimizeBox = false;
62 | this.MinimumSize = new System.Drawing.Size(1570, 612);
63 | this.Name = "CronExamples";
64 | this.ShowIcon = false;
65 | this.ShowInTaskbar = false;
66 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
67 | this.Text = "Cron examples";
68 | this.Load += new System.EventHandler(this.CronExamples_Load);
69 | this.ResumeLayout(false);
70 | this.PerformLayout();
71 |
72 | }
73 |
74 | #endregion
75 |
76 | private System.Windows.Forms.TextBox textBox1;
77 | }
78 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/CronExamples.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System;
5 | using System.Windows.Forms;
6 |
7 | namespace RecurringIntegrationsScheduler.Forms
8 | {
9 | public partial class CronExamples : Form
10 | {
11 | public CronExamples()
12 | {
13 | InitializeComponent();
14 | }
15 |
16 | private void CronExamples_Load(object sender, EventArgs e)
17 | {
18 | textBox1.SelectionStart = 0;
19 | textBox1.SelectionLength = 0;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/DataJobForm.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using RecurringIntegrationsScheduler.Properties;
5 | using RecurringIntegrationsScheduler.Settings;
6 | using System;
7 | using System.Text;
8 | using System.Windows.Forms;
9 |
10 | namespace RecurringIntegrationsScheduler.Forms
11 | {
12 | public partial class DataJobForm : Form
13 | {
14 | public DataJobForm()
15 | {
16 | InitializeComponent();
17 | }
18 |
19 | public DataJob DataJob { get; set; }
20 |
21 | private void DataJobForm_Load(object sender, EventArgs e)
22 | {
23 | comboBox1.DataSource = Enum.GetValues(typeof(DataJobType));
24 |
25 | if (DataJob != null)
26 | {
27 | Text = Resources.Edit_data_job;
28 | textBox1.Text = DataJob.Name;
29 | textBox2.Text = DataJob.ActivityId;
30 | textBox3.Text = DataJob.EntityName;
31 | comboBox1.SelectedItem = DataJob.Type;
32 | }
33 | else
34 | {
35 | Text = Resources.Add_data_job;
36 | }
37 | }
38 |
39 | private bool InputIsValid()
40 | {
41 | var message = new StringBuilder();
42 |
43 | if (string.IsNullOrEmpty(textBox1.Text))
44 | message.AppendLine(Resources.Friendly_name_is_required);
45 | if (string.IsNullOrEmpty(textBox2.Text))
46 | {
47 | message.AppendLine(Resources.Activity_Id_is_required);
48 | }
49 | else
50 | {
51 | var isValid = Guid.TryParse(textBox2.Text, out var guidOutput);
52 | if (!isValid)
53 | message.AppendLine(Resources.Activity_Id_is_invalid);
54 | }
55 |
56 | if (message.Length > 0)
57 | MessageBox.Show(message.ToString(), Resources.Validation_error, MessageBoxButtons.OK,
58 | MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
59 | return message.Length == 0;
60 | }
61 |
62 | private void ButtonOK_Click(object sender, EventArgs e)
63 | {
64 | if (InputIsValid())
65 | DataJob = new DataJob
66 | {
67 | Name = textBox1.Text,
68 | ActivityId = textBox2.Text,
69 | EntityName = textBox3.Text,
70 | Type = (DataJobType) comboBox1.SelectedItem
71 | };
72 | else
73 | DialogResult = DialogResult.None;
74 | }
75 |
76 | private void ComboBox1_SelectedIndexChanged(object sender, EventArgs e)
77 | {
78 | textBox3.Enabled = (DataJobType) comboBox1.SelectedItem == DataJobType.Upload;
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/DataJobForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/Scheduler/Forms/InstanceForm.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using RecurringIntegrationsScheduler.Properties;
5 | using RecurringIntegrationsScheduler.Settings;
6 | using System;
7 | using System.Text;
8 | using System.Windows.Forms;
9 |
10 | namespace RecurringIntegrationsScheduler.Forms
11 | {
12 | public partial class InstanceForm : Form
13 | {
14 | public InstanceForm()
15 | {
16 | InitializeComponent();
17 | }
18 |
19 | public Instance Instance { get; set; }
20 |
21 | private void InstanceForm_Load(object sender, EventArgs e)
22 | {
23 | if (Instance != null)
24 | {
25 | Text = Resources.Edit_instance;
26 | textBox1.Text = Instance.Name;
27 | textBox2.Text = Instance.AosUri;
28 | textBox3.Text = Instance.AzureAuthEndpoint;
29 | textBox4.Text = Instance.AadTenant;
30 | checkBox1.Checked = Instance.UseADAL;
31 | }
32 | else
33 | {
34 | Text = Resources.Add_instance;
35 | textBox3.Text = @"https://login.microsoftonline.com";
36 | }
37 | }
38 |
39 | private bool InputIsValid()
40 | {
41 | var message = new StringBuilder();
42 |
43 | if (string.IsNullOrEmpty(textBox1.Text))
44 | message.AppendLine(Resources.Friendly_name_is_required);
45 | if (string.IsNullOrEmpty(textBox2.Text))
46 | message.AppendLine(Resources.AOS_URL_is_required);
47 | else if (!CheckUrl(textBox2.Text))
48 | message.AppendLine(Resources.AOS_URL_is_invalid);
49 | if (string.IsNullOrEmpty(textBox3.Text))
50 | message.AppendLine(Resources.Authentication_endpoint_is_required);
51 | else if (!CheckUrl(textBox3.Text))
52 | message.AppendLine(Resources.Authentication_endpoint_URL_is_invalid);
53 | if (string.IsNullOrEmpty(textBox4.Text))
54 | message.AppendLine(Resources.Tenant_Id_is_required);
55 |
56 | if (message.Length > 0)
57 | MessageBox.Show(message.ToString(), Resources.Validation_error, MessageBoxButtons.OK,
58 | MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
59 | return message.Length == 0;
60 | }
61 |
62 | private static bool CheckUrl(string url)
63 | {
64 | var result = Uri.TryCreate(url, UriKind.Absolute, out Uri uriResult)
65 | && ((uriResult.Scheme == Uri.UriSchemeHttp) || (uriResult.Scheme == Uri.UriSchemeHttps));
66 | return result;
67 | }
68 |
69 | private void ButtonOK_Click(object sender, EventArgs e)
70 | {
71 | if (InputIsValid())
72 | Instance = new Instance
73 | {
74 | Name = textBox1.Text,
75 | AosUri = textBox2.Text.TrimEnd('/'),
76 | AzureAuthEndpoint = textBox3.Text.TrimEnd('/'),
77 | AadTenant = textBox4.Text,
78 | UseADAL = checkBox1.Checked
79 | };
80 | else
81 | DialogResult = DialogResult.None;
82 | }
83 | }
84 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/InstanceForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/Scheduler/Forms/JobGroupForm.Designer.cs:
--------------------------------------------------------------------------------
1 | using RecurringIntegrationsScheduler.Properties;
2 |
3 | namespace RecurringIntegrationsScheduler.Forms
4 | {
5 | partial class JobGroupForm
6 | {
7 | ///
8 | /// Required designer variable.
9 | ///
10 | private System.ComponentModel.IContainer components = null;
11 |
12 | ///
13 | /// Clean up any resources being used.
14 | ///
15 | /// true if managed resources should be disposed; otherwise, false.
16 | protected override void Dispose(bool disposing)
17 | {
18 | if (disposing && (components != null))
19 | {
20 | components.Dispose();
21 | }
22 | base.Dispose(disposing);
23 | }
24 |
25 | #region Windows Form Designer generated code
26 |
27 | ///
28 | /// Required method for Designer support - do not modify
29 | /// the contents of this method with the code editor.
30 | ///
31 | private void InitializeComponent()
32 | {
33 | this.panel1 = new System.Windows.Forms.Panel();
34 | this.ButtonCancel = new System.Windows.Forms.Button();
35 | this.ButtonOK = new System.Windows.Forms.Button();
36 | this.label1 = new System.Windows.Forms.Label();
37 | this.textBox1 = new System.Windows.Forms.TextBox();
38 | this.panel1.SuspendLayout();
39 | this.SuspendLayout();
40 | //
41 | // panel1
42 | //
43 | this.panel1.Controls.Add(this.ButtonCancel);
44 | this.panel1.Controls.Add(this.ButtonOK);
45 | this.panel1.Controls.Add(this.label1);
46 | this.panel1.Controls.Add(this.textBox1);
47 | this.panel1.Location = new System.Drawing.Point(18, 18);
48 | this.panel1.Margin = new System.Windows.Forms.Padding(4);
49 | this.panel1.Name = "panel1";
50 | this.panel1.Size = new System.Drawing.Size(538, 150);
51 | this.panel1.TabIndex = 0;
52 | //
53 | // ButtonCancel
54 | //
55 | this.ButtonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
56 | this.ButtonCancel.Location = new System.Drawing.Point(267, 86);
57 | this.ButtonCancel.Margin = new System.Windows.Forms.Padding(4);
58 | this.ButtonCancel.Name = "ButtonCancel";
59 | this.ButtonCancel.Size = new System.Drawing.Size(125, 52);
60 | this.ButtonCancel.TabIndex = 9;
61 | this.ButtonCancel.Text = global::RecurringIntegrationsScheduler.Properties.Resources.Cancel;
62 | this.ButtonCancel.UseVisualStyleBackColor = true;
63 | //
64 | // ButtonOK
65 | //
66 | this.ButtonOK.DialogResult = System.Windows.Forms.DialogResult.OK;
67 | this.ButtonOK.Location = new System.Drawing.Point(133, 86);
68 | this.ButtonOK.Margin = new System.Windows.Forms.Padding(4);
69 | this.ButtonOK.Name = "ButtonOK";
70 | this.ButtonOK.Size = new System.Drawing.Size(125, 52);
71 | this.ButtonOK.TabIndex = 8;
72 | this.ButtonOK.Text = global::RecurringIntegrationsScheduler.Properties.Resources.OK;
73 | this.ButtonOK.UseVisualStyleBackColor = true;
74 | this.ButtonOK.Click += new System.EventHandler(this.ButtonOK_Click);
75 | //
76 | // label1
77 | //
78 | this.label1.AutoSize = true;
79 | this.label1.Location = new System.Drawing.Point(22, 32);
80 | this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
81 | this.label1.Name = "label1";
82 | this.label1.Size = new System.Drawing.Size(184, 25);
83 | this.label1.TabIndex = 1;
84 | this.label1.Text = "RIS job group name";
85 | //
86 | // textBox1
87 | //
88 | this.textBox1.Location = new System.Drawing.Point(214, 27);
89 | this.textBox1.Margin = new System.Windows.Forms.Padding(4);
90 | this.textBox1.Name = "textBox1";
91 | this.textBox1.Size = new System.Drawing.Size(296, 29);
92 | this.textBox1.TabIndex = 0;
93 | //
94 | // JobGroupForm
95 | //
96 | this.AcceptButton = this.ButtonOK;
97 | this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 24F);
98 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
99 | this.CancelButton = this.ButtonCancel;
100 | this.ClientSize = new System.Drawing.Size(568, 165);
101 | this.Controls.Add(this.panel1);
102 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
103 | this.Margin = new System.Windows.Forms.Padding(4);
104 | this.MaximizeBox = false;
105 | this.MaximumSize = new System.Drawing.Size(592, 229);
106 | this.MinimizeBox = false;
107 | this.Name = "JobGroupForm";
108 | this.ShowIcon = false;
109 | this.ShowInTaskbar = false;
110 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
111 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
112 | this.Load += new System.EventHandler(this.JobGroupForm_Load);
113 | this.panel1.ResumeLayout(false);
114 | this.panel1.PerformLayout();
115 | this.ResumeLayout(false);
116 |
117 | }
118 |
119 | #endregion
120 |
121 | private System.Windows.Forms.Panel panel1;
122 | private System.Windows.Forms.Button ButtonCancel;
123 | private System.Windows.Forms.Button ButtonOK;
124 | private System.Windows.Forms.Label label1;
125 | private System.Windows.Forms.TextBox textBox1;
126 | }
127 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/JobGroupForm.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using RecurringIntegrationsScheduler.Properties;
5 | using RecurringIntegrationsScheduler.Settings;
6 | using System;
7 | using System.Text;
8 | using System.Windows.Forms;
9 |
10 | namespace RecurringIntegrationsScheduler.Forms
11 | {
12 | public partial class JobGroupForm : Form
13 | {
14 | public JobGroupForm()
15 | {
16 | InitializeComponent();
17 | }
18 |
19 | public JobGroup JobGroup { get; set; }
20 |
21 | private void JobGroupForm_Load(object sender, EventArgs e)
22 | {
23 | if (JobGroup != null)
24 | {
25 | Text = Resources.Edit_job_group;
26 | textBox1.Text = JobGroup.Name;
27 | }
28 | else
29 | {
30 | Text = Resources.Add_job_group;
31 | }
32 | }
33 |
34 | private bool InputIsValid()
35 | {
36 | var message = new StringBuilder();
37 |
38 | if (string.IsNullOrEmpty(textBox1.Text))
39 | message.AppendLine(Resources.Job_group_name_is_required);
40 |
41 | if (message.Length > 0)
42 | MessageBox.Show(message.ToString(), Resources.Validation_error, MessageBoxButtons.OK,
43 | MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
44 | return message.Length == 0;
45 | }
46 |
47 | private void ButtonOK_Click(object sender, EventArgs e)
48 | {
49 | if (InputIsValid())
50 | JobGroup = new JobGroup
51 | {
52 | Name = textBox1.Text
53 | };
54 | else
55 | DialogResult = DialogResult.None;
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/JobGroupForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/Scheduler/Forms/UserForm.Designer.cs:
--------------------------------------------------------------------------------
1 | using RecurringIntegrationsScheduler.Properties;
2 |
3 | namespace RecurringIntegrationsScheduler.Forms
4 | {
5 | partial class UserForm
6 | {
7 | ///
8 | /// Required designer variable.
9 | ///
10 | private System.ComponentModel.IContainer components = null;
11 |
12 | ///
13 | /// Clean up any resources being used.
14 | ///
15 | /// true if managed resources should be disposed; otherwise, false.
16 | protected override void Dispose(bool disposing)
17 | {
18 | if (disposing && (components != null))
19 | {
20 | components.Dispose();
21 | }
22 | base.Dispose(disposing);
23 | }
24 |
25 | #region Windows Form Designer generated code
26 |
27 | ///
28 | /// Required method for Designer support - do not modify
29 | /// the contents of this method with the code editor.
30 | ///
31 | private void InitializeComponent()
32 | {
33 | this.panel1 = new System.Windows.Forms.Panel();
34 | this.ButtonCancel = new System.Windows.Forms.Button();
35 | this.ButtonOK = new System.Windows.Forms.Button();
36 | this.label2 = new System.Windows.Forms.Label();
37 | this.textBox2 = new System.Windows.Forms.TextBox();
38 | this.label1 = new System.Windows.Forms.Label();
39 | this.textBox1 = new System.Windows.Forms.TextBox();
40 | this.panel1.SuspendLayout();
41 | this.SuspendLayout();
42 | //
43 | // panel1
44 | //
45 | this.panel1.Controls.Add(this.ButtonCancel);
46 | this.panel1.Controls.Add(this.ButtonOK);
47 | this.panel1.Controls.Add(this.label2);
48 | this.panel1.Controls.Add(this.textBox2);
49 | this.panel1.Controls.Add(this.label1);
50 | this.panel1.Controls.Add(this.textBox1);
51 | this.panel1.Location = new System.Drawing.Point(13, 12);
52 | this.panel1.Name = "panel1";
53 | this.panel1.Size = new System.Drawing.Size(360, 112);
54 | this.panel1.TabIndex = 0;
55 | //
56 | // ButtonCancel
57 | //
58 | this.ButtonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
59 | this.ButtonCancel.Location = new System.Drawing.Point(186, 74);
60 | this.ButtonCancel.Name = "ButtonCancel";
61 | this.ButtonCancel.Size = new System.Drawing.Size(91, 35);
62 | this.ButtonCancel.TabIndex = 9;
63 | this.ButtonCancel.Text = Resources.Cancel;
64 | this.ButtonCancel.UseVisualStyleBackColor = true;
65 | //
66 | // ButtonOK
67 | //
68 | this.ButtonOK.DialogResult = System.Windows.Forms.DialogResult.OK;
69 | this.ButtonOK.Location = new System.Drawing.Point(89, 74);
70 | this.ButtonOK.Name = "ButtonOK";
71 | this.ButtonOK.Size = new System.Drawing.Size(91, 35);
72 | this.ButtonOK.TabIndex = 8;
73 | this.ButtonOK.Text = Resources.OK;
74 | this.ButtonOK.UseVisualStyleBackColor = true;
75 | this.ButtonOK.Click += new System.EventHandler(this.ButtonOK_Click);
76 | //
77 | // label2
78 | //
79 | this.label2.AutoSize = true;
80 | this.label2.Location = new System.Drawing.Point(44, 49);
81 | this.label2.Name = "label2";
82 | this.label2.Size = new System.Drawing.Size(69, 17);
83 | this.label2.TabIndex = 3;
84 | this.label2.Text = Resources.Password;
85 | //
86 | // textBox2
87 | //
88 | this.textBox2.Location = new System.Drawing.Point(119, 46);
89 | this.textBox2.Name = "textBox2";
90 | this.textBox2.PasswordChar = '●';
91 | this.textBox2.Size = new System.Drawing.Size(209, 22);
92 | this.textBox2.TabIndex = 2;
93 | //
94 | // label1
95 | //
96 | this.label1.AutoSize = true;
97 | this.label1.Location = new System.Drawing.Point(27, 21);
98 | this.label1.Name = "label1";
99 | this.label1.Size = new System.Drawing.Size(86, 17);
100 | this.label1.TabIndex = 1;
101 | this.label1.Text = Resources.Login_UPN;
102 | //
103 | // textBox1
104 | //
105 | this.textBox1.Location = new System.Drawing.Point(119, 18);
106 | this.textBox1.Name = "textBox1";
107 | this.textBox1.Size = new System.Drawing.Size(209, 22);
108 | this.textBox1.TabIndex = 0;
109 | //
110 | // UserForm
111 | //
112 | this.AcceptButton = this.ButtonOK;
113 | this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
114 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
115 | this.CancelButton = this.ButtonCancel;
116 | this.ClientSize = new System.Drawing.Size(380, 132);
117 | this.Controls.Add(this.panel1);
118 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
119 | this.MaximizeBox = false;
120 | this.MaximumSize = new System.Drawing.Size(398, 179);
121 | this.MinimizeBox = false;
122 | this.Name = "UserForm";
123 | this.ShowIcon = false;
124 | this.ShowInTaskbar = false;
125 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
126 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
127 | this.Load += new System.EventHandler(this.UserForm_Load);
128 | this.panel1.ResumeLayout(false);
129 | this.panel1.PerformLayout();
130 | this.ResumeLayout(false);
131 |
132 | }
133 |
134 | #endregion
135 |
136 | private System.Windows.Forms.Panel panel1;
137 | private System.Windows.Forms.Button ButtonCancel;
138 | private System.Windows.Forms.Button ButtonOK;
139 | private System.Windows.Forms.Label label2;
140 | private System.Windows.Forms.TextBox textBox2;
141 | private System.Windows.Forms.Label label1;
142 | private System.Windows.Forms.TextBox textBox1;
143 | }
144 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/UserForm.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using RecurringIntegrationsScheduler.Properties;
5 | using RecurringIntegrationsScheduler.Settings;
6 | using System;
7 | using System.Text;
8 | using System.Windows.Forms;
9 |
10 | namespace RecurringIntegrationsScheduler.Forms
11 | {
12 | public partial class UserForm : Form
13 | {
14 | public UserForm()
15 | {
16 | InitializeComponent();
17 | }
18 |
19 | public User User { get; set; }
20 |
21 | private void UserForm_Load(object sender, EventArgs e)
22 | {
23 | if (User != null)
24 | {
25 | Text = Resources.Edit_user;
26 | textBox1.Text = User.Login;
27 | textBox2.Text = User.Password;
28 | }
29 | else
30 | {
31 | Text = Resources.Add_user;
32 | }
33 | }
34 |
35 | private bool InputIsValid()
36 | {
37 | var message = new StringBuilder();
38 |
39 | if (string.IsNullOrEmpty(textBox1.Text))
40 | message.AppendLine(Resources.User_login_is_required);
41 | if (string.IsNullOrEmpty(textBox2.Text))
42 | message.AppendLine(Resources.User_password_is_required);
43 |
44 | if (message.Length > 0)
45 | MessageBox.Show(message.ToString(), Resources.Validation_error, MessageBoxButtons.OK,
46 | MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
47 | return message.Length == 0;
48 | }
49 |
50 | private void ButtonOK_Click(object sender, EventArgs e)
51 | {
52 | if (InputIsValid())
53 | User = new User
54 | {
55 | Login = textBox1.Text,
56 | Password = textBox2.Text
57 | };
58 | else
59 | DialogResult = DialogResult.None;
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/Scheduler/Forms/UserForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/Scheduler/Forms/ValidateConnection.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/Scheduler/FormsHelper.cs:
--------------------------------------------------------------------------------
1 | using Quartz;
2 | using RecurringIntegrationsScheduler.Properties;
3 | using System;
4 | using System.Linq;
5 | using System.Windows.Forms;
6 |
7 | namespace RecurringIntegrationsScheduler
8 | {
9 | internal class FormsHelper
10 | {
11 | public static int DropDownWidth(ComboBox myCombo)
12 | {
13 | int minWidth = 1;
14 | foreach (var item in myCombo.Items)
15 | {
16 | int temp = TextRenderer.MeasureText(item.ToString(), myCombo.Font).Width;
17 | if (temp > minWidth)
18 | {
19 | minWidth = temp;
20 | }
21 | }
22 | return minWidth;
23 | }
24 |
25 | public static DateTimeOffset? GetScheduleForCron(string cronexpression, DateTimeOffset date)
26 | {
27 | try
28 | {
29 | var cron = new CronExpression(cronexpression);
30 | return cron.GetNextValidTimeAfter(date);
31 | }
32 | catch (Exception ex)
33 | {
34 | MessageBox.Show(ex.Message, Resources.Cron_expression_is_invalid);
35 | return DateTimeOffset.MinValue;
36 | }
37 | }
38 |
39 | public static void SetDropDownsWidth(Control parentCtrl)
40 | {
41 | parentCtrl.Controls
42 | .OfType()
43 | .ToList()
44 | .ForEach(t => t.DropDownWidth = DropDownWidth(t));
45 |
46 | foreach (Control c in parentCtrl.Controls)
47 | {
48 | SetDropDownsWidth(c);
49 | }
50 | }
51 |
52 | public static void TrimTextBoxes(Control parentCtrl)
53 | {
54 | parentCtrl.Controls //Trim all textboxes
55 | .OfType()
56 | .ToList()
57 | .ForEach(t => t.Text = t.Text.Trim());
58 |
59 | foreach (Control c in parentCtrl.Controls)
60 | {
61 | TrimTextBoxes(c);
62 | }
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/Scheduler/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // This file is used by Code Analysis to maintain SuppressMessage
2 | // attributes that are applied to this project.
3 | // Project-level suppressions either have no target or are given
4 | // a specific target and scoped to a namespace, type, member, etc.
5 |
6 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "", Scope = "member", Target = "~M:RecurringIntegrationsScheduler.Forms.UploadJobV3.GetScheduleForCron(System.String,System.DateTimeOffset)~System.Nullable{System.DateTimeOffset}")]
7 |
--------------------------------------------------------------------------------
/Scheduler/Program.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using Bluegrams.Application;
5 | using RecurringIntegrationsScheduler.Forms;
6 | using System;
7 | using System.Windows.Forms;
8 |
9 | namespace RecurringIntegrationsScheduler
10 | {
11 | internal static class Program
12 | {
13 | ///
14 | /// The main entry point for the application.
15 | ///
16 | [STAThread]
17 | private static void Main()
18 | {
19 | PortableSettingsProvider.ApplyProvider(Properties.Settings.Default);
20 | Application.EnableVisualStyles();
21 | Application.SetCompatibleTextRenderingDefault(false);
22 | Application.Run(new MainForm());
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/Scheduler/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Recurring Integrations Scheduler")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("Microsoft")]
15 | [assembly: AssemblyProduct("Recurring Integrations Scheduler")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 |
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 |
27 | [assembly: Guid("4F945CF2-CF0C-4A90-AB34-2354A260B4AF")]
--------------------------------------------------------------------------------
/Scheduler/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | UploadErrors
7 |
8 |
9 | UploadSuccess
10 |
11 |
12 | ProcessingSuccess
13 |
14 |
15 | Errors
16 |
17 |
18 | Input
19 |
20 |
21 | ProcessingErrors
22 |
23 |
24 | True
25 |
26 |
27 | <?xml version="1.0" encoding="utf-16"?>
28 | <ArrayOfDataJob xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
29 | <DataJob>
30 | <Name>Customers import</Name>
31 | <ActivityId>00000000-0000-0000-0000-000000000000</ActivityId>
32 | <EntityName>Customers</EntityName>
33 | <Type>Download</Type>
34 | </DataJob>
35 | </ArrayOfDataJob>
36 |
37 |
38 | <?xml version="1.0" encoding="utf-16"?>
39 | <ArrayOfInstance xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
40 | <Instance>
41 | <Name>Contoso PROD</Name>
42 | <AosUri>https://contoso.production.operations.dynamics.com</AosUri>
43 | <AzureAuthEndpoint>https://login.microsoftonline.com</AzureAuthEndpoint>
44 | <AadTenant>contoso.com</AadTenant>
45 | </Instance>
46 | </ArrayOfInstance>
47 |
48 |
49 | <?xml version="1.0" encoding="utf-16"?>
50 | <ArrayOfUser xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
51 | <User>
52 | <Login>admin@contoso.com</Login>
53 | <Password>pass@word1</Password>
54 | </User>
55 | </ArrayOfUser>
56 |
57 |
58 | <?xml version="1.0" encoding="utf-16"?>
59 | <ArrayOfJobGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
60 | <JobGroup>
61 | <Name>Import jobs</Name>
62 | </JobGroup>
63 | <JobGroup>
64 | <Name>Export jobs</Name>
65 | </JobGroup>
66 | <JobGroup>
67 | <Name>Download jobs</Name>
68 | </JobGroup>
69 | <JobGroup>
70 | <Name>Upload jobs</Name>
71 | </JobGroup>
72 | </ArrayOfJobGroup>
73 |
74 |
75 | <?xml version="1.0" encoding="utf-16"?>
76 | <ArrayOfAadApplication xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
77 | <AadApplication>
78 | <Name>User impersonation</Name>
79 | <ClientId>00000000-0000-0000-0000-000000000000</ClientId>
80 | <Secret />
81 | <AuthenticationType>User</AuthenticationType>
82 | </AadApplication>
83 | <AadApplication>
84 | <Name>Service to Service</Name>
85 | <ClientId>00000000-0000-0000-0000-000000000000</ClientId>
86 | <Secret />
87 | <AuthenticationType>Service</AuthenticationType>
88 | </AadApplication>
89 | </ArrayOfAadApplication>
90 |
91 |
92 |
--------------------------------------------------------------------------------
/Scheduler/Settings/Settings.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System;
5 | using System.ComponentModel;
6 |
7 | namespace RecurringIntegrationsScheduler.Settings
8 | {
9 | [Serializable]
10 | public class AadApplication
11 | {
12 | ///
13 | /// Gets or sets the name.
14 | ///
15 | ///
16 | /// The name.
17 | ///
18 | public string Name { get; set; }
19 |
20 | ///
21 | /// Gets or sets the client identifier.
22 | ///
23 | ///
24 | /// The client identifier.
25 | ///
26 | public string ClientId { get; set; }
27 |
28 | ///
29 | /// Gets or sets the secret.
30 | ///
31 | ///
32 | /// The secret.
33 | ///
34 | public string Secret { get; set; }
35 |
36 | ///
37 | /// Gets or sets the type.
38 | ///
39 | ///
40 | /// The type.
41 | ///
42 | public AuthenticationType AuthenticationType { get; set; }
43 | }
44 |
45 | ///
46 | ///
47 | ///
48 | public enum AuthenticationType
49 | {
50 | User,
51 | Service
52 | }
53 |
54 | ///
55 | ///
56 | ///
57 | ///
58 | public class AadApplications : BindingList
59 | {
60 | }
61 |
62 | ///
63 | ///
64 | ///
65 | [Serializable]
66 | public class DataJob
67 | {
68 | ///
69 | /// Gets or sets the name.
70 | ///
71 | ///
72 | /// The name.
73 | ///
74 | public string Name { get; set; }
75 |
76 | ///
77 | /// Gets or sets the activity identifier.
78 | ///
79 | ///
80 | /// The activity identifier.
81 | ///
82 | public string ActivityId { get; set; }
83 |
84 | ///
85 | /// Gets or sets the name of the entity.
86 | ///
87 | ///
88 | /// The name of the entity.
89 | ///
90 | public string EntityName { get; set; }
91 |
92 | ///
93 | /// Gets or sets the type.
94 | ///
95 | ///
96 | /// The type.
97 | ///
98 | public DataJobType Type { get; set; }
99 | }
100 |
101 | ///
102 | ///
103 | ///
104 | public enum DataJobType
105 | {
106 | Download,
107 | Upload
108 | }
109 |
110 | ///
111 | ///
112 | ///
113 | ///
114 | public class DataJobs : BindingList
115 | {
116 | }
117 |
118 | ///
119 | ///
120 | ///
121 | [Serializable]
122 | public class Instance
123 | {
124 | ///
125 | /// Gets or sets the name.
126 | ///
127 | ///
128 | /// The name.
129 | ///
130 | public string Name { get; set; }
131 |
132 | ///
133 | /// Gets or sets the aos URI.
134 | ///
135 | ///
136 | /// The aos URI.
137 | ///
138 | public string AosUri { get; set; }
139 |
140 | ///
141 | /// Gets or sets the azure authentication endpoint.
142 | ///
143 | ///
144 | /// The azure authentication endpoint.
145 | ///
146 | public string AzureAuthEndpoint { get; set; }
147 |
148 | ///
149 | /// Gets or sets the aad tenant.
150 | ///
151 | ///
152 | /// The aad tenant.
153 | ///
154 | public string AadTenant { get; set; }
155 |
156 | ///
157 | /// Gets or sets the use ADAL.
158 | ///
159 | ///
160 | /// The aad tenant.
161 | ///
162 | public bool UseADAL { get; set; }
163 | }
164 |
165 | ///
166 | ///
167 | ///
168 | ///
169 | public class Instances : BindingList
170 | {
171 | }
172 |
173 | ///
174 | ///
175 | ///
176 | [Serializable]
177 | public class JobGroup
178 | {
179 | ///
180 | /// Gets or sets the name.
181 | ///
182 | ///
183 | /// The name.
184 | ///
185 | public string Name { get; set; }
186 | }
187 |
188 | ///
189 | ///
190 | ///
191 | ///
192 | public class JobGroups : BindingList
193 | {
194 | }
195 |
196 | ///
197 | ///
198 | ///
199 | [Serializable]
200 | public class User
201 | {
202 | ///
203 | /// Gets or sets the login.
204 | ///
205 | ///
206 | /// The login.
207 | ///
208 | public string Login { get; set; }
209 |
210 | ///
211 | /// Gets or sets the password.
212 | ///
213 | ///
214 | /// The password.
215 | ///
216 | public string Password { get; set; }
217 | }
218 |
219 | ///
220 | ///
221 | ///
222 | ///
223 | public class Users : BindingList
224 | {
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/Scheduler/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Scheduler/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Server/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
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 |
--------------------------------------------------------------------------------
/Server/Configuration.cs:
--------------------------------------------------------------------------------
1 | //https://github.com/quartznet/quartznet
2 | using System;
3 | using System.Collections.Specialized;
4 | using System.Configuration;
5 | using log4net;
6 |
7 | namespace RecurringIntegrationsScheduler.Server
8 | {
9 | ///
10 | /// Configuration for the Quartz server.
11 | ///
12 | public class Configuration
13 | {
14 | private static readonly ILog log = LogManager.GetLogger(typeof(Configuration));
15 |
16 | private const string PrefixServerConfiguration = "quartz.server";
17 | private const string KeyServiceName = PrefixServerConfiguration + ".serviceName";
18 | private const string KeyServiceDisplayName = PrefixServerConfiguration + ".serviceDisplayName";
19 | private const string KeyServiceDescription = PrefixServerConfiguration + ".serviceDescription";
20 | private const string KeyServerImplementationType = PrefixServerConfiguration + ".type";
21 |
22 | private const string DefaultServiceName = "QuartzServer";
23 | private const string DefaultServiceDisplayName = "Quartz Server";
24 | private const string DefaultServiceDescription = "Quartz Job Scheduling Server";
25 | private static readonly string DefaultServerImplementationType = typeof(QuartzServer).AssemblyQualifiedName!;
26 |
27 | private static readonly NameValueCollection? configuration;
28 |
29 | ///
30 | /// Initializes the class.
31 | ///
32 | static Configuration()
33 | {
34 | try
35 | {
36 | configuration = (NameValueCollection) ConfigurationManager.GetSection("quartz");
37 | }
38 | catch (Exception e)
39 | {
40 | log.Warn("could not read configuration using ConfigurationManager.GetSection: " + e.Message);
41 | }
42 | }
43 |
44 | ///
45 | /// Gets the name of the service.
46 | ///
47 | /// The name of the service.
48 | public static string ServiceName => GetConfigurationOrDefault(KeyServiceName, DefaultServiceName);
49 |
50 | ///
51 | /// Gets the display name of the service.
52 | ///
53 | /// The display name of the service.
54 | public static string ServiceDisplayName => GetConfigurationOrDefault(KeyServiceDisplayName, DefaultServiceDisplayName);
55 |
56 | ///
57 | /// Gets the service description.
58 | ///
59 | /// The service description.
60 | public static string ServiceDescription => GetConfigurationOrDefault(KeyServiceDescription, DefaultServiceDescription);
61 |
62 | ///
63 | /// Gets the type name of the server implementation.
64 | ///
65 | /// The type of the server implementation.
66 | public static string ServerImplementationType => GetConfigurationOrDefault(KeyServerImplementationType, DefaultServerImplementationType);
67 |
68 | ///
69 | /// Returns configuration value with given key. If configuration
70 | /// for the does not exists, return the default value.
71 | ///
72 | /// Key to read configuration with.
73 | /// Default value to return if configuration is not found
74 | /// The configuration value.
75 | private static string GetConfigurationOrDefault(string configurationKey, string defaultValue)
76 | {
77 | string? retValue = null;
78 | if (configuration != null)
79 | {
80 | retValue = configuration[configurationKey];
81 | }
82 |
83 | if (retValue == null || retValue.Trim().Length == 0)
84 | {
85 | retValue = defaultValue;
86 | }
87 | return retValue;
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Server/IQuartzServer.cs:
--------------------------------------------------------------------------------
1 | //https://github.com/quartznet/quartznet
2 | using System.Threading.Tasks;
3 |
4 | namespace RecurringIntegrationsScheduler.Server
5 | {
6 | ///
7 | /// Service interface for core Quartz.NET server.
8 | ///
9 | public interface IQuartzServer
10 | {
11 | ///
12 | /// Initializes the instance of .
13 | /// Initialization will only be called once in server's lifetime.
14 | ///
15 | Task Initialize();
16 |
17 | ///
18 | /// Starts this instance.
19 | ///
20 | void Start();
21 |
22 | ///
23 | /// Stops this instance.
24 | ///
25 | void Stop();
26 |
27 | ///
28 | /// Pauses all activity in scheduler.
29 | ///
30 | void Pause();
31 |
32 | ///
33 | /// Resumes all activity in server.
34 | ///
35 | void Resume();
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Server/Program.cs:
--------------------------------------------------------------------------------
1 | //https://github.com/quartznet/quartznet
2 | using System;
3 | using System.IO;
4 | using System.Reflection;
5 | using log4net.Config;
6 | using Topshelf;
7 |
8 | namespace RecurringIntegrationsScheduler.Server
9 | {
10 | ///
11 | /// The server's main entry point.
12 | ///
13 | public static class Program
14 | {
15 | ///
16 | /// Main.
17 | ///
18 | public static void Main()
19 | {
20 | // change from service account's dir to more logical one
21 | Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory);
22 |
23 | var logRepository = log4net.LogManager.GetRepository(Assembly.GetEntryAssembly());
24 | XmlConfigurator.Configure(logRepository, new FileInfo("log4net.config"));
25 |
26 | HostFactory.Run(x =>
27 | {
28 | x.RunAsLocalSystem();
29 |
30 | x.SetDescription(Configuration.ServiceDescription);
31 | x.SetDisplayName(Configuration.ServiceDisplayName);
32 | x.SetServiceName(Configuration.ServiceName);
33 |
34 | x.Service(factory =>
35 | {
36 | QuartzServer server = QuartzServerFactory.CreateServer();
37 | server.Initialize().GetAwaiter().GetResult();
38 | return server;
39 | });
40 | });
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/Server/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 |
7 | // General Information about an assembly is controlled through the following
8 | // set of attributes. Change these attribute values to modify the information
9 | // associated with an assembly.
10 |
11 | [assembly: AssemblyTitle("Recurring Integrations Scheduler Server")]
12 | [assembly: AssemblyDescription("")]
13 | [assembly: AssemblyConfiguration("")]
14 | [assembly: AssemblyCompany("")]
15 | [assembly: AssemblyProduct("Recurring Integrations Scheduler")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 |
23 | [assembly: ComVisible(false)]
24 |
25 | // The following GUID is for the ID of the typelib if this project is exposed to COM
26 |
27 | [assembly: Guid("a83c017e-6a29-4039-8970-46ab95bee619")]
--------------------------------------------------------------------------------
/Server/QuartzServer.cs:
--------------------------------------------------------------------------------
1 | //https://github.com/quartznet/quartznet
2 | using System;
3 | using System.Threading.Tasks;
4 | using log4net;
5 | using Quartz;
6 | using Quartz.Impl;
7 | using Topshelf;
8 |
9 | namespace RecurringIntegrationsScheduler.Server
10 | {
11 | ///
12 | /// The main server logic.
13 | ///
14 | public class QuartzServer : ServiceControl, IQuartzServer
15 | {
16 | private readonly ILog logger;
17 | private ISchedulerFactory schedulerFactory = null!;
18 | private IScheduler scheduler = null!;
19 |
20 | ///
21 | /// Initializes a new instance of the class.
22 | ///
23 | public QuartzServer()
24 | {
25 | logger = LogManager.GetLogger(GetType());
26 | }
27 |
28 | ///
29 | /// Initializes the instance of the class.
30 | ///
31 | public virtual async Task Initialize()
32 | {
33 | try
34 | {
35 | schedulerFactory = CreateSchedulerFactory();
36 | scheduler = await GetScheduler().ConfigureAwait(false);
37 | }
38 | catch (Exception e)
39 | {
40 | logger.Error("Server initialization failed:" + e.Message, e);
41 | throw;
42 | }
43 | }
44 |
45 | ///
46 | /// Gets the scheduler with which this server should operate with.
47 | ///
48 | ///
49 | protected virtual Task GetScheduler()
50 | {
51 | return schedulerFactory.GetScheduler();
52 | }
53 |
54 | ///
55 | /// Returns the current scheduler instance (usually created in
56 | /// using the method).
57 | ///
58 | protected virtual IScheduler Scheduler => scheduler;
59 |
60 | ///
61 | /// Creates the scheduler factory that will be the factory
62 | /// for all schedulers on this instance.
63 | ///
64 | ///
65 | protected virtual ISchedulerFactory CreateSchedulerFactory()
66 | {
67 | return new StdSchedulerFactory();
68 | }
69 |
70 | ///
71 | /// Starts this instance, delegates to scheduler.
72 | ///
73 | public virtual void Start()
74 | {
75 | try
76 | {
77 | scheduler.Start();
78 | }
79 | catch (Exception ex)
80 | {
81 | logger.Fatal($"Scheduler start failed: {ex.Message}", ex);
82 | throw;
83 | }
84 |
85 | logger.Info("Scheduler started successfully");
86 | }
87 |
88 | ///
89 | /// Stops this instance, delegates to scheduler.
90 | ///
91 | public virtual void Stop()
92 | {
93 | try
94 | {
95 | scheduler.Shutdown(true);
96 | }
97 | catch (Exception ex)
98 | {
99 | logger.Error($"Scheduler stop failed: {ex.Message}", ex);
100 | throw;
101 | }
102 |
103 | logger.Info("Scheduler shutdown complete");
104 | }
105 |
106 | ///
107 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
108 | ///
109 | public virtual void Dispose()
110 | {
111 | // no-op for now
112 | }
113 |
114 | ///
115 | /// Pauses all activity in scheduler.
116 | ///
117 | public virtual void Pause()
118 | {
119 | scheduler.PauseAll();
120 | }
121 |
122 | ///
123 | /// Resumes all activity in server.
124 | ///
125 | public void Resume()
126 | {
127 | scheduler.ResumeAll();
128 | }
129 |
130 | ///
131 | /// TopShelf's method delegated to .
132 | ///
133 | public bool Start(HostControl hostControl)
134 | {
135 | Start();
136 | return true;
137 | }
138 |
139 | ///
140 | /// TopShelf's method delegated to .
141 | ///
142 | public bool Stop(HostControl hostControl)
143 | {
144 | Stop();
145 | return true;
146 | }
147 |
148 | ///
149 | /// TopShelf's method delegated to .
150 | ///
151 | public bool Pause(HostControl hostControl)
152 | {
153 | Pause();
154 | return true;
155 | }
156 |
157 | ///
158 | /// TopShelf's method delegated to .
159 | ///
160 | public bool Continue(HostControl hostControl)
161 | {
162 | Resume();
163 | return true;
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/Server/QuartzServerFactory.cs:
--------------------------------------------------------------------------------
1 | //https://github.com/quartznet/quartznet
2 |
3 | using System;
4 | using log4net;
5 |
6 | namespace RecurringIntegrationsScheduler.Server
7 | {
8 | ///
9 | /// Factory class to create Quartz server implementations from.
10 | ///
11 | public class QuartzServerFactory
12 | {
13 | private static readonly ILog logger = LogManager.GetLogger(typeof (QuartzServerFactory));
14 |
15 | ///
16 | /// Creates a new instance of an Quartz.NET server core.
17 | ///
18 | ///
19 | public static QuartzServer CreateServer()
20 | {
21 | string typeName = Configuration.ServerImplementationType;
22 |
23 | Type t = Type.GetType(typeName, true)!;
24 |
25 | logger.Debug("Creating new instance of server type '" + typeName + "'");
26 | QuartzServer retValue = (QuartzServer) Activator.CreateInstance(t)!;
27 | logger.Debug("Instance successfully created");
28 | return retValue;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/Server/Schedule.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Server/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/Setup/README.md:
--------------------------------------------------------------------------------
1 | **Recurring Integrations Scheduler.iss** file contains packaging instructions for [Inno Setup](http://www.jrsoftware.org/isinfo.php) installer.
2 |
3 | Example command to create installation package (executed from root folder of the solution):
4 | ```
5 | "C:\Program Files (x86)\Inno Setup 6\Compil32.exe" /cc ".\Setup\Recurring Integrations Scheduler.iss"
6 | ```
7 |
--------------------------------------------------------------------------------
/Setup/Recurring Integrations Scheduler.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/Recurring-Integrations-Scheduler/b6f09b6671e46490e3b5fcd192ce1ae4cc6593a5/Setup/Recurring Integrations Scheduler.ico
--------------------------------------------------------------------------------
/Third Party Notices.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/Recurring-Integrations-Scheduler/b6f09b6671e46490e3b5fcd192ce1ae4cc6593a5/Third Party Notices.txt
--------------------------------------------------------------------------------
/Version.cs:
--------------------------------------------------------------------------------
1 | /* Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT License. */
3 |
4 | using System.Reflection;
5 | [assembly: AssemblyVersion("3.5.0.0")]
6 |
--------------------------------------------------------------------------------