├── .gitattributes
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE.md
├── README.md
├── builds
└── PSScriptsService_v1.1.7371.25098.zip
└── src
├── PSScriptsService.sln
└── PSScriptsService
├── Globals.cs
├── Install.cmd
├── PSScriptsService.Designer.cs
├── PSScriptsService.cs
├── PSScriptsService.csproj
├── PSScriptsService.resx
├── Program.cs
├── ProjectInstaller.Designer.cs
├── ProjectInstaller.cs
├── ProjectInstaller.resx
├── Properties
├── AssemblyInfo.cs
├── Settings.Designer.cs
└── Settings.settings
├── ScriptLauncher.cs
├── ServiceLib.cs
├── Uninstall.cmd
├── app.config
├── packages.config
└── settings.json
/.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 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Transcriptase
2 |
3 | Alone in the field is not a warrior! We want you to contribute to this project in easy and transparent way:
4 |
5 | - Reporting a bug
6 | - Discussing the current state of the code
7 | - Submitting a fix
8 | - Proposing new features
9 | - Becoming a maintainer
10 |
11 | ## We Develop with Github
12 |
13 | We use github to host code, to track issues and feature requests, as well as accept pull requests.
14 |
15 | ## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests
16 |
17 | Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your pull requests:
18 |
19 | 1. Fork the repo and create your branch from `master`.
20 | 2. If you've added code that should be tested, add tests.
21 | 3. If you've changed APIs, update the documentation.
22 | 4. Ensure the test suite passes.
23 | 5. Make sure your code lints.
24 | 6. Issue that pull request!
25 |
26 | ## Any contributions you make will be under the ISC Software License
27 |
28 | In short, when you submit code changes, your submissions are understood to be under the same [ISC License](https://choosealicense.com/licenses/isc/) that covers the project. Feel free to contact the maintainers if that's a concern.
29 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Internet Systems Consortium license
2 | ===================================
3 |
4 | Copyright (c) `2020`, `Maksym Sadovnychyy (MAKS-IT)`
5 | Website: `https://maks-it.com`
6 | Email: `commercial@maks-it.com`
7 |
8 | Permission to use, copy, modify, and/or distribute this software for any purpose
9 | with or without fee is hereby granted, provided that the above copyright notice
10 | and this permission notice appear in all copies.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
13 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
14 | FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
15 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
16 | OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
17 | TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
18 | THIS SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Power Shell Scripts Service
2 |
3 | > Deprecated version! Please see renewed program [Unified Scheduler Service](https://github.com/MAKS-IT-COM/uscheduler)
4 |
5 | This project has an aim to allow **System Administrators** and also to who **Thinks to be System Administrator** to launch **Power Shell** scripts as **Windows Service**.
6 |
7 | ## Latest builds
8 |
9 | * [PSScriptsService_v1.1.7371.25098](builds/PSScriptsService_v1.1.7371.25098.zip)
10 |
11 | ## How It Works
12 |
13 | When you **install** and then **start** this **Windows Service**, it scans default folder in its root **PowerShellScripts**, then serches for default script **StartScript.ps1** in parent directories:
14 |
15 | ```
16 | .
17 | ├── ...
18 | ├── PowerShellScripts
19 | | ├── SomeStuff_1
20 | | | ├── ...
21 | | | ├── StartScript.ps1
22 | | | └── ...
23 | | ├── SomeStuff_2
24 | | | ├── ...
25 | | | ├── StartScript.ps1
26 | | | └── ...
27 | | └── ...
28 | └── ...
29 | ```
30 |
31 | To each script following command parameters are being passed:
32 |
33 | ```C#
34 | myCommand.Parameters.Add(new CommandParameter("Automated", true));
35 | myCommand.Parameters.Add(new CommandParameter("CurrentDateTimeUtc", DateTime.UtcNow.ToString("o")));
36 | ```
37 |
38 | which you can retrieve on the script side this way:
39 |
40 | ```PowerShell
41 | [CmdletBinding()]
42 | param (
43 | [switch]$Automated,
44 | [string]$CurrentDateTime
45 | )
46 |
47 | if($CurrentDateTime) {
48 | [datetime]$CurrentDateTime = [datetime]::parseexact($CurrentDateTime, 'dd/MM/yyyy HH:mm:ss', $null)
49 | }
50 |
51 | Write-Host "Automated: $Automated" -ForegroundColor Green
52 | Write-Host "CurrentDateTime: $CurrentDateTime" -ForegroundColor Green
53 | ```
54 |
55 | Thanks to that, it's possible to create standalone scripts or automated scheduled scripts, which will be executed according to the script managed schedule logic.
56 |
57 | Every script is launched in its **own thread**, so if one crashes, others are able to run anyway:
58 |
59 | ```bash
60 | Power Shell Scripts Service Thread
61 | └── DoWork Thread
62 | ├── SomeStuff_1 / StartScript.ps1 Thread
63 | ├── SomeStuff_2 / StartScript.ps1 Thread
64 | └── ...
65 | ```
66 |
67 | > It's set to execute only **signed** scrips by default, but if you don't care about your environment security, it's possible to launch them in **unrestricted** mode.
68 | >
69 | > Continue to read to see other possible settings...
70 |
71 | ## Customizations
72 |
73 | Here are all currently available customizations, managed into handy json file:
74 |
75 | ```json
76 | {
77 | "ServiceName": "PSScriptsService",
78 | "Description": "Windows service, which allows you to invoke PowerShell Scripts",
79 | "DisplayName": "PowerShell Scripts Service",
80 | "LogPath": "",
81 | "LogSize": "20",
82 | "ScriptsPath": "",
83 | "TargetScript": "",
84 | "SignedScripts": true
85 | }
86 | ```
87 |
88 | Let's see each one:
89 |
90 | * ServiceName - System service name. I suggest to use short names without spaces or other strange characters. See [What are valid characters in a Windows service (key) name?](https://stackoverflow.com/questions/801280/what-are-valid-characters-in-a-windows-service-key-name).
91 | * Description - Description you wants to give to this service. Just put something very serious and technically complex to admire what kind of DUDE you are!
92 | * DisplayName - Same thing like for ServiceName, but you are free to use spaces.
93 | * LogPath - If empty, the service will create **Logs** folder in its root.
94 | * LogSize - Integer Megabytes.
95 | * ScriptsPath - If empty, the service will check **PowerShellScripts** folder in its root.
96 | * TargetScript - Normally service is looking for default **StartScript.ps1**, you are free to specify another **entry point script** name.
97 | * SignedScripts - **true** for **AllSigned** or **false** for **Unrestricted**
98 |
99 | You can create multiple services just create another service root folder and set different: **ServiceName**, **Description**, **DisplayName**; also: **LogPath**, **ScriptsPath**; in case of custom values.
100 |
101 | ## Install and Uninstall Power Shell Scripts Service
102 |
103 | I have prepared 2 ***.cmd** files to simplify service system integration:
104 |
105 | Install.cmd
106 |
107 | ```bat
108 | "%~dp0PSScriptsService.exe" install
109 | pause
110 | ```
111 |
112 | and
113 |
114 | Uninstall.cmd
115 |
116 | ```bat
117 | "%~dp0PSScriptsService.exe" uninstall
118 | pause
119 | ```
120 |
121 | >These ***.cmd** files have to be launched with **Admin** privileges.
122 |
123 | After installation you have to start your newly created windows service: Win+R -> services.msc -> Enter -> Search by DisplayName.
124 |
125 | ## Real World usage examples
126 |
127 | ### Run React js and .Net Core WebApi on Windows Server
128 |
129 | One of the possible usages of this solution is to run **Node js Express** **(React js Prerendering Server)** and **.Net Core WebApi** on windows machines.
130 |
131 | StartScript.ps1
132 |
133 | ```powershell
134 | Start-Process -FilePath "npm" -Args "run-script webpack_prod" -WorkingDirectory "C:\source\repos\SomeProject\code\frontend" -NoNewWindow -Wait
135 | Start-Process -FilePath "npm" -Args "run-script start" -WorkingDirectory "C:\source\repos\SomeProject\code\frontend" -NoNewWindow
136 | Start-Process -FilePath "dotnet" -Args "run --configuration Release --project C:\source\repos\SomeProject\code\backend\SomeProject.csproj" -NoNewWindow
137 | ```
138 |
139 | This simple script will be launched in **Power Shell Scripts Service** context, build and start you frontend **npm bundle** and backend **WebApi**.
140 |
--------------------------------------------------------------------------------
/builds/PSScriptsService_v1.1.7371.25098.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/maks-it/PSScriptsService/be08998d236f6b32570bb46539d48b09fc7f7d49/builds/PSScriptsService_v1.1.7371.25098.zip
--------------------------------------------------------------------------------
/src/PSScriptsService.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29728.190
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PSScriptsService", "PSScriptsService\PSScriptsService.csproj", "{F60E9DC1-BD1D-4E41-A04E-CB3E105B8CF5}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {F60E9DC1-BD1D-4E41-A04E-CB3E105B8CF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {F60E9DC1-BD1D-4E41-A04E-CB3E105B8CF5}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {F60E9DC1-BD1D-4E41-A04E-CB3E105B8CF5}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {F60E9DC1-BD1D-4E41-A04E-CB3E105B8CF5}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {59786937-84D2-40CD-9A0F-3D95932594D6}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/src/PSScriptsService/Globals.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Internet Systems Consortium license
4 | *
5 | * Copyright (c) 2020 Maksym Sadovnychyy (MAKS-IT)
6 | * Website: https://maks-it.com
7 | * Email: commercial@maks-it.com
8 | *
9 | * Permission to use, copy, modify, and/or distribute this software for any purpose
10 | * with or without fee is hereby granted, provided that the above copyright notice
11 | * and this permission notice appear in all copies.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
15 | * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
17 | * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
19 | * THIS SOFTWARE.
20 | */
21 |
22 | using System;
23 | using System.IO;
24 | using Newtonsoft.Json;
25 |
26 | namespace PSScriptsService
27 | {
28 | public class Settings
29 | {
30 | public dynamic settings { get; set; }
31 |
32 | public Settings()
33 | {
34 | settings = JsonConvert.DeserializeObject(File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "settings.json"));
35 |
36 | if (!File.Exists((string)settings.LogPath))
37 | {
38 | string logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
39 | if (!Directory.Exists(logDir))
40 | Directory.CreateDirectory(logDir);
41 |
42 | settings.LogPath = Path.Combine(logDir, (string)settings.ServiceName + ".log");
43 | File.Create((string)settings.LogPath).Dispose();
44 | }
45 |
46 |
47 | if (!Directory.Exists((string)settings.ScriptsPath))
48 | {
49 | settings.ScriptsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "PowerShellScripts");
50 | Directory.CreateDirectory((string)settings.ScriptsPath);
51 | }
52 |
53 | if (!File.Exists((string)settings.TargetScript))
54 | settings.TargetScript = "StartScript.ps1";
55 |
56 | }
57 | }
58 |
59 | public static class Globals {
60 | public static dynamic settings = new Settings().settings;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/PSScriptsService/Install.cmd:
--------------------------------------------------------------------------------
1 | "%~dp0PSScriptsService.exe" install
2 | pause
--------------------------------------------------------------------------------
/src/PSScriptsService/PSScriptsService.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace PSScriptsService
2 | {
3 | partial class PSScriptsService
4 | {
5 | ///
6 | /// Variabile di progettazione necessaria.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Pulire le risorse in uso.
12 | ///
13 | /// ha valore true se le risorse gestite devono essere eliminate, false in caso contrario.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Codice generato da Progettazione componenti
24 |
25 | ///
26 | /// Metodo necessario per il supporto della finestra di progettazione. Non modificare
27 | /// il contenuto del metodo con l'editor di codice.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | //
32 | // PSScriptsService
33 | //
34 | this.ServiceName = "PSScriptsService";
35 |
36 | }
37 |
38 | #endregion
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/PSScriptsService/PSScriptsService.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Internet Systems Consortium license
4 | *
5 | * Copyright (c) 2020 Maksym Sadovnychyy (MAKS-IT)
6 | * Website: https://maks-it.com
7 | * Email: commercial@maks-it.com
8 | *
9 | * Permission to use, copy, modify, and/or distribute this software for any purpose
10 | * with or without fee is hereby granted, provided that the above copyright notice
11 | * and this permission notice appear in all copies.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
15 | * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
17 | * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
19 | * THIS SOFTWARE.
20 | */
21 |
22 | using System.ServiceProcess;
23 | using System.IO;
24 | using System.Threading;
25 | using PSScriptsService.ServiceLib;
26 |
27 | namespace PSScriptsService
28 | {
29 | public partial class PSScriptsService : ServiceBase
30 | {
31 | public Thread srvThread = null;
32 | public static Timer stateTimer = null;
33 |
34 | public PSScriptsService()
35 | {
36 | InitializeComponent();
37 |
38 | srvThread = new Thread(DoWork);
39 | srvThread.IsBackground = true;
40 | }
41 |
42 | protected override void OnStart(string[] args)
43 | {
44 | SrvLog.Write((string)(Globals.settings.ServiceName) + " started");
45 | srvThread.Start("PSScriptsService");
46 | }
47 |
48 | protected override void OnStop()
49 | {
50 | SrvLog.Write((string)(Globals.settings.ServiceName) + " stopped");
51 | }
52 |
53 | private static void DoWork(object data)
54 | {
55 | SrvLog.Write(string.Format("Thread Started: '{0}'", data.ToString()));
56 |
57 | string [] scriptsDir = Directory.GetDirectories((string)Globals.settings.ScriptsPath);
58 | if (scriptsDir.Length == 0) {
59 | SrvLog.Write(string.Format("Folder: '{0}' has no scripts", (string)Globals.settings.ScriptsPath));
60 | }
61 |
62 | foreach (string scriptDir in scriptsDir)
63 | {
64 | string scriptPath = Path.Combine(scriptDir, (string)Globals.settings.TargetScript);
65 |
66 | if (File.Exists(scriptPath))
67 | {
68 | Thread scriptThread = new Thread(ScriptWorker);
69 | scriptThread.IsBackground = true;
70 | scriptThread.Start(scriptPath);
71 | }
72 | else
73 | {
74 | SrvLog.Write("Script folder " + Directory.GetParent(scriptPath).Name + " doesn't contain " + Path.GetFileName(scriptPath) + ". Ignored!");
75 | }
76 |
77 |
78 | }
79 | }
80 |
81 | private static void ScriptWorker(object data)
82 | {
83 | string scriptPath = (string)data;
84 |
85 | SrvLog.Write(string.Format("Script Started: '{0}'", Directory.GetParent(scriptPath).Name));
86 |
87 | // Create an AutoResetEvent to signal the timeout threshold in the
88 | // timer callback has been reached.
89 | var autoEvent = new AutoResetEvent(false);
90 |
91 | TimerCallback ScriptLauncher = new ScriptLauncher(scriptPath).RunScript;
92 | stateTimer = new Timer(ScriptLauncher, autoEvent, 1000, 60000); //1 seconds delay and every 1 minute
93 |
94 | // When autoEvent signals, dispose of the timer.
95 | autoEvent.WaitOne();
96 | stateTimer.Dispose();
97 | }
98 | }
99 |
100 |
101 |
102 |
103 | }
--------------------------------------------------------------------------------
/src/PSScriptsService/PSScriptsService.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F60E9DC1-BD1D-4E41-A04E-CB3E105B8CF5}
8 | Exe
9 | Properties
10 | PSScriptsService
11 | PSScriptsService
12 | v4.8
13 | 512
14 | false
15 |
16 | publish\
17 | true
18 | Disk
19 | false
20 | Foreground
21 | 7
22 | Days
23 | false
24 | false
25 | true
26 | 0
27 | 1.0.0.%2a
28 | false
29 | true
30 |
31 |
32 | AnyCPU
33 | true
34 | full
35 | false
36 | bin\Debug\
37 | DEBUG;TRACE
38 | prompt
39 | 4
40 | false
41 |
42 |
43 | AnyCPU
44 | pdbonly
45 | true
46 | bin\Release\
47 | TRACE
48 | prompt
49 | 4
50 | false
51 |
52 |
53 |
54 |
55 |
56 |
57 | ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | ..\packages\System.Management.Automation.dll.10.0.10586.0\lib\net40\System.Management.Automation.dll
66 | True
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | Component
79 |
80 |
81 | ProjectInstaller.cs
82 |
83 |
84 | True
85 | True
86 | Settings.settings
87 |
88 |
89 | Component
90 |
91 |
92 | PSScriptsService.cs
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | ProjectInstaller.cs
103 |
104 |
105 | PSScriptsService.cs
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | Always
115 |
116 |
117 | Always
118 |
119 |
120 |
121 | SettingsSingleFileGenerator
122 | Settings.Designer.cs
123 |
124 |
125 | Always
126 |
127 |
128 |
129 |
130 | False
131 | Microsoft .NET Framework 4 %28x86 e x64%29
132 | true
133 |
134 |
135 | False
136 | .NET Framework 3.5 SP1 Client Profile
137 | false
138 |
139 |
140 | False
141 | .NET Framework 3.5 SP1
142 | false
143 |
144 |
145 | False
146 | Windows Installer 4.5
147 | true
148 |
149 |
150 |
151 |
152 |
153 | copy $(SolutionDir)\..\LICENSE.md $(ProjectDir)$(OutDir)
154 |
155 |
162 |
--------------------------------------------------------------------------------
/src/PSScriptsService/PSScriptsService.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 |
121 | False
122 |
123 |
--------------------------------------------------------------------------------
/src/PSScriptsService/Program.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Internet Systems Consortium license
4 | *
5 | * Copyright (c) 2020 Maksym Sadovnychyy (MAKS-IT)
6 | * Website: https://maks-it.com
7 | * Email: commercial@maks-it.com
8 | *
9 | * Permission to use, copy, modify, and/or distribute this software for any purpose
10 | * with or without fee is hereby granted, provided that the above copyright notice
11 | * and this permission notice appear in all copies.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
15 | * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
17 | * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
19 | * THIS SOFTWARE.
20 | */
21 |
22 | using System;
23 | using System.ServiceProcess;
24 | using System.Reflection;
25 | using System.Configuration.Install;
26 | using System.Linq;
27 |
28 |
29 | namespace PSScriptsService
30 | {
31 | static class Program
32 | {
33 | ///
34 | /// The main entry point for the application.
35 | ///
36 | ///
37 | static void Main(String[] args)
38 | {
39 | ServiceBase[] services = new ServiceBase[] {
40 | new PSScriptsService()
41 | };
42 |
43 | // UserInteractive mode
44 | if (Environment.UserInteractive)
45 | {
46 | if (System.Diagnostics.Debugger.IsAttached) {
47 | // Debug mode
48 | InteractiveService(services);
49 | }
50 | else {
51 | // Service actions mode
52 | InteractiveServiceArgs(args, services);
53 | }
54 | }
55 | else {
56 | // NonInteractive mode
57 | ServiceBase.Run(services);
58 | }
59 | }
60 |
61 | ///
62 | /// Interactive service
63 | ///
64 | ///
65 | static void InteractiveService(ServiceBase[] services)
66 | {
67 | Console.WriteLine();
68 | Console.WriteLine("Start service in interactive mode.");
69 | Console.WriteLine();
70 |
71 | // Get the method to invoke on each service to start it
72 | MethodInfo onStartMethod = typeof(ServiceBase).GetMethod("OnStart", BindingFlags.Instance | BindingFlags.NonPublic);
73 |
74 | // Start services loop
75 | foreach (ServiceBase service in services)
76 | {
77 | Console.Write("Starting {0} ... ", service.ServiceName);
78 | onStartMethod.Invoke(service, new object[] { new string[] { } });
79 | Console.WriteLine("Started");
80 | }
81 |
82 | // Waiting the end
83 | Console.WriteLine();
84 | Console.WriteLine("Press any key to stop service and end process...");
85 | Console.ReadKey();
86 | Console.WriteLine();
87 |
88 | // Get the method to invoke on each service to stop it
89 | MethodInfo onStopMethod = typeof(ServiceBase).GetMethod("OnStop", BindingFlags.Instance | BindingFlags.NonPublic);
90 |
91 | // Stop loop
92 | foreach (ServiceBase service in services)
93 | {
94 | Console.Write("Stopping {0} ... ", service.ServiceName);
95 | onStopMethod.Invoke(service, null);
96 | Console.WriteLine("Stopped");
97 | }
98 |
99 | Console.WriteLine();
100 | Console.WriteLine("All services are stopped.");
101 |
102 | // Waiting a key press to not return to VS directly
103 | if (System.Diagnostics.Debugger.IsAttached)
104 | {
105 | Console.WriteLine();
106 | Console.Write("---- Press any key to quit ----");
107 | Console.ReadKey();
108 | }
109 | }
110 |
111 |
112 | ///
113 | /// Interactive service arguments actions: install, uninstall, start and stop service
114 | ///
115 | ///
116 | static void InteractiveServiceArgs(string[] args, ServiceBase[] services) {
117 | try
118 | {
119 | bool success = false;
120 | args.ToList().ForEach(cmd => {
121 | switch (cmd.ToLower())
122 | {
123 | case "install":
124 | {
125 | ManagedInstallerClass.InstallHelper(new string[] { typeof(Program).Assembly.Location });
126 | success = true;
127 | break;
128 | }
129 | case "uninstall":
130 | {
131 | ManagedInstallerClass.InstallHelper(new string[] { "/u", typeof(Program).Assembly.Location });
132 | success = true;
133 | break;
134 | }
135 | case "start":
136 | {
137 | foreach (var service in services)
138 | {
139 | ServiceController sc = new ServiceController(service.ServiceName);
140 | sc.Start();
141 | sc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(10));
142 | success = true;
143 | }
144 | break;
145 | }
146 | case "stop":
147 | {
148 | foreach (var service in services)
149 | {
150 | ServiceController sc = new ServiceController(service.ServiceName);
151 | sc.Stop();
152 | sc.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
153 | success = true;
154 | }
155 | break;
156 | }
157 | }
158 | });
159 |
160 | if (!success) {
161 | Console.WriteLine("Usage : {0} [command] [command ...]", Environment.GetCommandLineArgs());
162 | Console.WriteLine("Commands : ");
163 | Console.WriteLine(" service.exe install : Install the service");
164 | Console.WriteLine(" service.exe uninstall : Uninstall the service");
165 | }
166 | }
167 | catch (Exception ex)
168 | {
169 | var bkpColor = Console.ForegroundColor;
170 | Console.ForegroundColor = ConsoleColor.Red;
171 | Console.WriteLine("Error : {0}", ex.GetBaseException().Message);
172 | Console.ForegroundColor = bkpColor;
173 | }
174 |
175 |
176 | }
177 |
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/src/PSScriptsService/ProjectInstaller.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace PSScriptsService
2 | {
3 | partial class ProjectInstaller
4 | {
5 | ///
6 | /// Variabile di progettazione necessaria.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Pulire le risorse in uso.
12 | ///
13 | /// ha valore true se le risorse gestite devono essere eliminate, false in caso contrario.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Codice generato da Progettazione componenti
24 |
25 | ///
26 | /// Metodo necessario per il supporto della finestra di progettazione. Non modificare
27 | /// il contenuto del metodo con l'editor di codice.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
32 | this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
33 | //
34 | // serviceProcessInstaller1
35 | //
36 | this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
37 | this.serviceProcessInstaller1.Password = null;
38 | this.serviceProcessInstaller1.Username = null;
39 | //
40 | // serviceInstaller1
41 | //
42 | this.serviceInstaller1.ServiceName = Globals.settings.ServiceName;
43 | this.serviceInstaller1.Description = Globals.settings.Description;
44 | this.serviceInstaller1.DisplayName = Globals.settings.DisplayName;
45 | this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
46 | //
47 | // ProjectInstaller
48 | //
49 | this.Installers.AddRange(new System.Configuration.Install.Installer[] {
50 | this.serviceProcessInstaller1,
51 | this.serviceInstaller1});
52 |
53 | }
54 |
55 | #endregion
56 |
57 | private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1;
58 | private System.ServiceProcess.ServiceInstaller serviceInstaller1;
59 | }
60 | }
--------------------------------------------------------------------------------
/src/PSScriptsService/ProjectInstaller.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Internet Systems Consortium license
4 | *
5 | * Copyright (c) 2020 Maksym Sadovnychyy (MAKS-IT)
6 | * Website: https://maks-it.com
7 | * Email: commercial@maks-it.com
8 | *
9 | * Permission to use, copy, modify, and/or distribute this software for any purpose
10 | * with or without fee is hereby granted, provided that the above copyright notice
11 | * and this permission notice appear in all copies.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
15 | * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
17 | * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
19 | * THIS SOFTWARE.
20 | */
21 |
22 | using System;
23 | using System.Collections;
24 | using System.Collections.Generic;
25 | using System.ComponentModel;
26 | using System.Configuration.Install;
27 | using System.Linq;
28 |
29 | namespace PSScriptsService
30 | {
31 | [RunInstaller(true)]
32 | public partial class ProjectInstaller : System.Configuration.Install.Installer
33 | {
34 | public ProjectInstaller()
35 | {
36 | InitializeComponent();
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/PSScriptsService/ProjectInstaller.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 |
121 | 17, 56
122 |
123 |
124 | 23, 51
125 |
126 |
127 | False
128 |
129 |
--------------------------------------------------------------------------------
/src/PSScriptsService/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // Le informazioni generali relative a un assembly sono controllate dal seguente
6 | // set di attributi. Per modificare le informazioni associate a un assembly
7 | // occorre quindi modificare i valori di questi attributi.
8 | [assembly: AssemblyTitle("PSScriptsService")]
9 | [assembly: AssemblyDescription("PowerShell Scripts Service")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyProduct("PSScriptsService")]
12 | [assembly: AssemblyCopyright("Copyright © 2020, Maksym Sadovnychyy (MAKS-IT)")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Se si imposta ComVisible su false, i tipi in questo assembly non saranno visibili
17 | // ai componenti COM. Se è necessario accedere a un tipo in questo assembly da
18 | // COM, impostare su true l'attributo ComVisible per tale tipo.
19 | [assembly: ComVisible(false)]
20 |
21 | // Se il progetto viene esposto a COM, il GUID che segue verrà utilizzato per creare l'ID della libreria dei tipi
22 | [assembly: Guid("04be6241-a8b0-4038-ae3e-6b5f68ae0b01")]
23 |
24 | // Le informazioni sulla versione di un assembly sono costituite dai seguenti quattro valori:
25 | //
26 | // Numero di versione principale
27 | // Numero di versione secondario
28 | // Numero build
29 | // Revisione
30 | //
31 | // È possibile specificare tutti i valori oppure impostare valori predefiniti per i numeri relativi alla revisione e alla build
32 | // utilizzando l'asterisco (*) come descritto di seguito:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.1.*")]
35 | [assembly: AssemblyCompany("MAKS-IT")]
36 |
--------------------------------------------------------------------------------
/src/PSScriptsService/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace PSScriptsService.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/PSScriptsService/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/PSScriptsService/ScriptLauncher.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Internet Systems Consortium license
4 | *
5 | * Copyright (c) 2020 Maksym Sadovnychyy (MAKS-IT)
6 | * Website: https://maks-it.com
7 | * Email: commercial@maks-it.com
8 | *
9 | * Permission to use, copy, modify, and/or distribute this software for any purpose
10 | * with or without fee is hereby granted, provided that the above copyright notice
11 | * and this permission notice appear in all copies.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
15 | * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
17 | * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
19 | * THIS SOFTWARE.
20 | */
21 |
22 | using System;
23 | using System.Threading;
24 | using System.Text;
25 | using System.IO;
26 | using System.Management.Automation;
27 | using System.Management.Automation.Runspaces;
28 | using PSScriptsService.ServiceLib;
29 |
30 | namespace PSScriptsService {
31 | class ScriptLauncher {
32 | private string scriptPath;
33 |
34 | public ScriptLauncher(string path) {
35 | scriptPath = path;
36 | }
37 |
38 | object lockObject = new object();
39 |
40 | // This method is called by the timer delegate.
41 | public void RunScript(Object stateInfo) {
42 | if (Monitor.TryEnter(lockObject)) {
43 | try {
44 | AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
45 |
46 | StringBuilder stringBuilder = new StringBuilder();
47 |
48 | Runspace rs = RunspaceFactory.CreateRunspace();
49 | rs.Open();
50 |
51 | PowerShell ps = PowerShell.Create();
52 | ps.Runspace = rs;
53 |
54 | string scriptPolicy = "Unrestricted";
55 | if ((bool)Globals.settings.SignedScripts)
56 | scriptPolicy = "AllSigned";
57 |
58 | ps.AddScript("Set-ExecutionPolicy -Scope Process -ExecutionPolicy " + scriptPolicy);
59 | ps.Invoke();
60 |
61 | ps.AddScript(string.Format("Get-AuthenticodeSignature \"{0}\"", scriptPath));
62 |
63 | foreach (PSObject result in ps.Invoke()) {
64 | if ((bool)Globals.settings.SignedScripts) {
65 | if (((Signature)result.BaseObject).Status != SignatureStatus.Valid) {
66 | SrvLog.Write("Script " + Directory.GetParent(scriptPath).Name + " Signature Error! Correct, and restart the service.");
67 |
68 | //signal the waiting thread
69 | autoEvent.Set();
70 |
71 | break;
72 | }
73 | }
74 |
75 | SrvLog.Write("Invoking: " + scriptPath);
76 |
77 | Command myCommand = new Command(scriptPath);
78 |
79 | // Pass -Automated switch and -CuttrentDateTimeUtc, as UTC ISO 8601 string
80 | myCommand.Parameters.Add(new CommandParameter("Automated", true));
81 | myCommand.Parameters.Add(new CommandParameter("CurrentDateTimeUtc", DateTime.UtcNow.ToString("o")));
82 |
83 | ps.Commands.Commands.Add(myCommand);
84 | ps.Invoke();
85 |
86 | /*foreach (PSObject obj in ps.Invoke())
87 | {
88 | SrvLog.Write(obj.ToString(), logPath);
89 | }*/
90 |
91 |
92 | //signal the waiting thread
93 | //autoEvent.Set();
94 | }
95 | }
96 | catch (Exception ex) {
97 | SrvLog.Write(ex.Message.ToString());
98 | }
99 | finally {
100 | Monitor.Exit(lockObject);
101 | }
102 | }
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/PSScriptsService/ServiceLib.cs:
--------------------------------------------------------------------------------
1 | /**
2 | * @license
3 | * Internet Systems Consortium license
4 | *
5 | * Copyright (c) 2020 Maksym Sadovnychyy (MAKS-IT)
6 | * Website: https://maks-it.com
7 | * Email: commercial@maks-it.com
8 | *
9 | * Permission to use, copy, modify, and/or distribute this software for any purpose
10 | * with or without fee is hereby granted, provided that the above copyright notice
11 | * and this permission notice appear in all copies.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
14 | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
15 | * FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
16 | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
17 | * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
19 | * THIS SOFTWARE.
20 | */
21 |
22 | using System;
23 | using System.IO;
24 |
25 | namespace PSScriptsService.ServiceLib {
26 | public static class SrvLog {
27 | public static void Write(string message) {
28 |
29 | //build the log path string, test again, testfff
30 | string logPath = (string)Globals.settings.LogPath;
31 |
32 | if (File.Exists(logPath) && new FileInfo(logPath).Length / 1048576 > (int)Globals.settings.LogSize)
33 | File.Delete(logPath);
34 |
35 | try {
36 | using (StreamWriter sw = new StreamWriter(logPath, true))
37 | sw.Write(DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss") + " - " + message + Environment.NewLine);
38 | }
39 | catch {
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/PSScriptsService/Uninstall.cmd:
--------------------------------------------------------------------------------
1 | "%~dp0PSScriptsService.exe" uninstall
2 | pause
--------------------------------------------------------------------------------
/src/PSScriptsService/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/PSScriptsService/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/PSScriptsService/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "ServiceName": "PSScriptsService",
3 | "Description": "Windows service, which allows you to invoke PowerShell Scripts",
4 | "DisplayName": "PowerShell Scripts Service",
5 | "LogPath": "",
6 | "LogSize": "20",
7 | "ScriptsPath": "",
8 | "TargetScript": "",
9 | "SignedScripts": true
10 | }
--------------------------------------------------------------------------------