├── .gitattributes
├── .gitignore
├── README.md
├── RemoteUpdate.png
├── RemoteUpdate.sln
├── RemoteUpdate
├── About.xaml
├── About.xaml.cs
├── App.xaml
├── App.xaml.cs
├── Credentials.xaml
├── Credentials.xaml.cs
├── Fixit.xaml
├── Fixit.xaml.cs
├── GifImage.cs
├── Global.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── PSScript.xaml
├── PSScript.xaml.cs
├── Password.xaml
├── Password.xaml.cs
├── Pictures
│ ├── Donate.gif
│ ├── RemoteUpdate.png
│ ├── checkmark.gif
│ ├── error.gif
│ ├── loading_gray.gif
│ ├── loading_lightgray.gif
│ ├── restart.gif
│ ├── restart.png
│ └── uac-shield.png
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── RemoteUpdate.csproj
├── RemoteUpdate.ico
├── Settings.xaml
├── Settings.xaml.cs
├── Tasks.cs
├── Worker.cs
├── app.config
└── packages.config
├── _config.yml
└── _layouts
└── default.html
/.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 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !?*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 |
235 | # RIA/Silverlight projects
236 | Generated_Code/
237 |
238 | # Backup & report files from converting an old project file
239 | # to a newer Visual Studio version. Backup files are not needed,
240 | # because we have git ;-)
241 | _UpgradeReport_Files/
242 | Backup*/
243 | UpgradeLog*.XML
244 | UpgradeLog*.htm
245 | ServiceFabricBackup/
246 | *.rptproj.bak
247 |
248 | # SQL Server files
249 | *.mdf
250 | *.ldf
251 | *.ndf
252 |
253 | # Business Intelligence projects
254 | *.rdl.data
255 | *.bim.layout
256 | *.bim_*.settings
257 | *.rptproj.rsuser
258 | *- Backup*.rdl
259 |
260 | # Microsoft Fakes
261 | FakesAssemblies/
262 |
263 | # GhostDoc plugin setting file
264 | *.GhostDoc.xml
265 |
266 | # Node.js Tools for Visual Studio
267 | .ntvs_analysis.dat
268 | node_modules/
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
277 | *.vbw
278 |
279 | # Visual Studio LightSwitch build output
280 | **/*.HTMLClient/GeneratedArtifacts
281 | **/*.DesktopClient/GeneratedArtifacts
282 | **/*.DesktopClient/ModelManifest.xml
283 | **/*.Server/GeneratedArtifacts
284 | **/*.Server/ModelManifest.xml
285 | _Pvt_Extensions
286 |
287 | # Paket dependency manager
288 | .paket/paket.exe
289 | paket-files/
290 |
291 | # FAKE - F# Make
292 | .fake/
293 |
294 | # JetBrains Rider
295 | .idea/
296 | *.sln.iml
297 |
298 | # CodeRush personal settings
299 | .cr/personal
300 |
301 | # Python Tools for Visual Studio (PTVS)
302 | __pycache__/
303 | *.pyc
304 |
305 | # Cake - Uncomment if you are using it
306 | # tools/**
307 | # !tools/packages.config
308 |
309 | # Tabs Studio
310 | *.tss
311 |
312 | # Telerik's JustMock configuration file
313 | *.jmconfig
314 |
315 | # BizTalk build output
316 | *.btp.cs
317 | *.btm.cs
318 | *.odx.cs
319 | *.xsd.cs
320 |
321 | # OpenCover UI analysis results
322 | OpenCover/
323 |
324 | # Azure Stream Analytics local run output
325 | ASALocalRun/
326 |
327 | # MSBuild Binary and Structured Log
328 | *.binlog
329 |
330 | # NVidia Nsight GPU debugger configuration file
331 | *.nvuser
332 |
333 | # MFractors (Xamarin productivity tool) working folder
334 | .mfractor/
335 |
336 | # Local History for Visual Studio
337 | .localhistory/
338 |
339 | # BeatPulse healthcheck temp database
340 | healthchecksdb
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | RemoteUpdate uses the Powershell Module PSWindowsUpdate to install Windows Updates on Remote Hosts without the need of scheduled jobs (like described here)
2 |
3 |
4 |
5 |
6 |
7 | It is meant for small environments where no SCCM or other solutions are existent or bearable.
8 | As default it is not possible to install Updates via Remote Powershell, therefore the tool uses a little workaround with a Powershell VirtualAccount.
9 |
10 | # Requirements:
11 | * Windows Server 2012 or newer
12 | * Powershell 5
13 | * .net Framework 4.7.2 on executing host
14 | * ICMP Echo allowed on the remote hosts
15 | * Default Firewall Rule "Windows Remote Management (HTTP-In)" enabled on the remote hosts
16 | * Administrative credentials on the remote hosts
17 | * Internet Access to download PSWindowsUpdate or PSWindowsUpdate already installed on the remote hosts
18 |
19 | # How To:
20 | * Add the DNS Name of the server you want to update
21 | * Choose between the options:
22 | * * Do you want to accept all available updates or choose by hand which one should be installed (-AcceptAll)
23 | * * Do You want driver updates installed/shown (-NotCategory Drivers)
24 | * * Do you want an automatic reboot after the installation (-AutoReboot)
25 | * * Do you want to see the Powershell GUI or just let it work in the background
26 | * * Do you want to get an email report (-SendReport –PSWUSettings)
27 | * Set your credentials. If you are in a domain and your user has admin rights you don't need this.
28 | * Save your settings for the next update (2 xml files will be created in the same directory, one for the servers and one for the general settings)
29 | * Choose between the options:
30 | * * Update: Runs the update process. Does not reboot the servers unless Reboot (-AutoReboot) selected (And the updates require reboot as determined by -AutoReboot)
31 | * * Pending: Only checks if the server is pending a reboot. Displays the reboot icon if a reboot is pending.
32 | * * Reboot: Only instantly restarts the computer (Restart-Computer -Force)
33 | * * Script - Opens a window to let you manually run a script.
34 |
35 | If you have a high amount of servers and want to start all at the same time, enable them with the last checkbox and press "Start All"
36 | For each server you selected or clicked start a powershell window will open and ask you which updates should be installed or show you the progress of the installation directly (if you checked AcceptAll)
37 |
38 | # FAQ
39 | * Are the credentials i saved safe? The credentials are encrypted with a SHA512 method. The EncryptionKey is your chosen password and the salt comes from the servername of each entry. Therefore it is not possible to determine if you use the same passwords on more servers. I hope it is good enough but can not guarantee anything.
40 | * Can i use it in a productive environment? Please decide for yourself after you tested it in your lab
41 | * What do the colors mean? Green = Host pingable; Red = Not pingable; Violet = No IP found for the DNS Record;
42 | * Why won't it work with IPs? Cause in the default settings Remote Powershell won't accept IPs, therefore you would have to activate Remote Powershell via HTTPS (Port 5986 instead of Port 5985) and i would have to do some work for this, which i haven't till today.
43 | * Do you want feedback or feature requests? I would highly appreciate it and i'm going to try my best to develop it further
44 | * How can i contact you? via Mail
45 |
--------------------------------------------------------------------------------
/RemoteUpdate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aimaat/RemoteUpdate/7037bf1a549b6d5b9ec00b9c8cefce2daa63601a/RemoteUpdate.png
--------------------------------------------------------------------------------
/RemoteUpdate.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}") = "RemoteUpdate", "RemoteUpdate\RemoteUpdate.csproj", "{4F495525-DC49-4D90-9335-7A823AD59C6A}"
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 | {4F495525-DC49-4D90-9335-7A823AD59C6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {4F495525-DC49-4D90-9335-7A823AD59C6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {4F495525-DC49-4D90-9335-7A823AD59C6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {4F495525-DC49-4D90-9335-7A823AD59C6A}.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 = {4D0D580F-0E62-479E-BD76-0A362754CC81}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/RemoteUpdate/About.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
20 |
21 |
26 |
31 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/RemoteUpdate/About.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Windows;
3 |
4 | namespace RemoteUpdate
5 | {
6 | ///
7 | /// Interaction logic for About.xaml
8 | ///
9 | public partial class About : Window
10 | {
11 | string strVirtualAccountName = "VirtualAccount";
12 | public About(string strVATmp)
13 | {
14 | InitializeComponent();
15 | WindowStartupLocation = WindowStartupLocation.CenterOwner;
16 | Owner = Application.Current.MainWindow;
17 | strVirtualAccountName = strVATmp;
18 | LabelVersion.Content = System.Reflection.Assembly.GetEntryAssembly().GetName().Version.ToString();
19 | }
20 | private void ButtonDonate_Click(object sender, RoutedEventArgs e)
21 | {
22 | Process.Start("https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=6JQTFNSEJZD9J&source=url");
23 | }
24 | private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
25 | {
26 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
27 | e.Handled = true;
28 | }
29 |
30 | private void ButtonExit_Click(object sender, RoutedEventArgs e)
31 | {
32 | this.Close();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/RemoteUpdate/App.xaml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/RemoteUpdate/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace RemoteUpdate
4 | {
5 | ///
6 | /// Interaction logic for App.xaml
7 | ///
8 | public partial class App : Application
9 | {
10 | private static string[] Args;
11 | private void Application_Startup(object sender, StartupEventArgs e)
12 | {
13 | if (e.Args.Length > 0)
14 | {
15 | bool bExit = false;
16 | Args = e.Args;
17 | for (int ii = 0; ii < Args.Length; ii++)
18 | {
19 | switch (Args[ii].ToString(System.Globalization.CultureInfo.CurrentCulture))
20 | {
21 | case "WinRMService":
22 | Tasks.SetServiceStartup("winrm", "auto");
23 | bExit = true;
24 | continue;
25 | case "WinRMStart":
26 | Tasks.StartService("winrm");
27 | bExit = true;
28 | continue;
29 | case "TrustedHosts":
30 | Tasks.SetTrustedHosts("*");
31 | bExit = true;
32 | continue;
33 | }
34 | }
35 | if (bExit)
36 | {
37 | System.Environment.Exit(0);
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/RemoteUpdate/Credentials.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/RemoteUpdate/Credentials.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 |
4 | namespace RemoteUpdate
5 | {
6 | ///
7 | /// Interaction logic for Credentials.xaml
8 | ///
9 | public partial class Credentials : Window
10 | {
11 | int iLabelID;
12 | public Credentials(int iTmpID)
13 | {
14 | InitializeComponent();
15 | WindowStartupLocation = WindowStartupLocation.CenterOwner;
16 | Owner = Application.Current.MainWindow;
17 | iLabelID = iTmpID;
18 | if (Global.TableRuntime.Rows[iLabelID]["Password"].ToString().Length != 0)
19 | {
20 | PasswordBoxPassword.Password = Global.TableRuntime.Rows[iLabelID]["Password"].ToString();
21 | }
22 | if (Global.TableRuntime.Rows[iLabelID]["Username"].ToString().Length != 0)
23 | {
24 | TextboxUsername.Text = Global.TableRuntime.Rows[iLabelID]["Username"].ToString();
25 | }
26 | }
27 | private void ButtonCancel(object sender, RoutedEventArgs e)
28 | {
29 | this.Close();
30 | }
31 | private void UsernameGotFocus(object sender, RoutedEventArgs e)
32 | {
33 | if (sender.GetType().Name == "TextBox")
34 | {
35 | (sender as TextBox).SelectAll();
36 | }
37 | else
38 | {
39 | (sender as PasswordBox).SelectAll();
40 | }
41 | }
42 | private void ButtonOk(object sender, RoutedEventArgs e)
43 | {
44 | if (TextboxUsername.Text != "Username")
45 | {
46 | Tasks.LockAndWriteDataTable(Global.TableRuntime, iLabelID, "Username", TextboxUsername.Text, 100);
47 | //Global.TableRuntime.Rows[iLabelID]["Username"] = TextboxUsername.Text;
48 | }
49 | if (PasswordBoxPassword.Password != "ABC")
50 | {
51 | Tasks.LockAndWriteDataTable(Global.TableRuntime, iLabelID, "Password", PasswordBoxPassword.Password, 100);
52 | //Global.TableRuntime.Rows[iLabelID]["Password"] = PasswordBoxPassword.Password;
53 | }
54 | this.Close();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/RemoteUpdate/Fixit.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/RemoteUpdate/Fixit.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace RemoteUpdate
4 | {
5 | ///
6 | /// Interaction logic for Fixit.xaml
7 | ///
8 | public partial class Fixit : Window
9 | {
10 | public Fixit()
11 | {
12 | InitializeComponent();
13 | WindowStartupLocation = WindowStartupLocation.CenterOwner;
14 | Owner = Application.Current.MainWindow;
15 | if (Tasks.IsAdministrator())
16 | {
17 | ImageUAC.Visibility = System.Windows.Visibility.Collapsed;
18 | }
19 | }
20 | private void ButtonFixitCancel_Click(object sender, RoutedEventArgs e)
21 | {
22 | this.DialogResult = false;
23 | this.Close();
24 | }
25 | private void ButtonFixitOK_Click(object sender, RoutedEventArgs e)
26 | {
27 | this.DialogResult = true;
28 | this.Close();
29 | }
30 | private void WinRMTrustedHosts_Checked(object sender, RoutedEventArgs e)
31 | {
32 | WinRMServiceStart.IsChecked = true;
33 | WinRMServiceStart.IsEnabled = false;
34 | }
35 | private void WinRMTrustedHosts_Unchecked(object sender, RoutedEventArgs e)
36 | {
37 | WinRMServiceStart.IsEnabled = true;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/RemoteUpdate/GifImage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 | using System.Windows.Controls;
4 | using System.Windows.Media.Animation;
5 | using System.Windows.Media.Imaging;
6 |
7 | namespace RemoteUpdate
8 | {
9 | class GifImage : Image
10 | {
11 | private bool _isInitialized;
12 | private GifBitmapDecoder _gifDecoder;
13 | private Int32Animation _animation;
14 | public int FrameIndex
15 | {
16 | get { return (int)GetValue(FrameIndexProperty); }
17 | set { SetValue(FrameIndexProperty, value); }
18 | }
19 | private void Initialize()
20 | {
21 | _gifDecoder = new GifBitmapDecoder(new Uri(this.Source.ToString(Global.cultures)), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
22 | _animation = new Int32Animation(0, _gifDecoder.Frames.Count - 1, new Duration(new TimeSpan(0, 0, 0, _gifDecoder.Frames.Count / 10, (int)((_gifDecoder.Frames.Count / 10.0 - _gifDecoder.Frames.Count / 10) * 1000))));
23 | _animation.RepeatBehavior = RepeatBehavior.Forever;
24 | this.Source = _gifDecoder.Frames[0];
25 |
26 | _isInitialized = true;
27 | }
28 | static GifImage()
29 | {
30 | VisibilityProperty.OverrideMetadata(typeof(GifImage),
31 | new FrameworkPropertyMetadata(VisibilityPropertyChanged));
32 | }
33 | private static void VisibilityPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
34 | {
35 | if ((Visibility)e.NewValue == Visibility.Visible)
36 | {
37 | ((GifImage)sender).StartAnimation();
38 | }
39 | else
40 | {
41 | ((GifImage)sender).StopAnimation();
42 | }
43 | }
44 | public static readonly DependencyProperty FrameIndexProperty =
45 | DependencyProperty.Register("FrameIndex", typeof(int), typeof(GifImage), new UIPropertyMetadata(0, new PropertyChangedCallback(ChangingFrameIndex)));
46 | static void ChangingFrameIndex(DependencyObject obj, DependencyPropertyChangedEventArgs ev)
47 | {
48 | var gifImage = obj as GifImage;
49 | gifImage.Source = gifImage._gifDecoder.Frames[(int)ev.NewValue];
50 | }
51 | ///
52 | /// Defines whether the animation starts on it's own
53 | ///
54 | public bool AutoStart
55 | {
56 | get { return (bool)GetValue(AutoStartProperty); }
57 | set { SetValue(AutoStartProperty, value); }
58 | }
59 | public static readonly DependencyProperty AutoStartProperty =
60 | DependencyProperty.Register("AutoStart", typeof(bool), typeof(GifImage), new UIPropertyMetadata(false, AutoStartPropertyChanged));
61 | private static void AutoStartPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
62 | {
63 | if ((bool)e.NewValue)
64 | (sender as GifImage).StartAnimation();
65 | }
66 | public string GifSource
67 | {
68 | get { return (string)GetValue(GifSourceProperty); }
69 | set { SetValue(GifSourceProperty, value); }
70 | }
71 | public static readonly DependencyProperty GifSourceProperty =
72 | DependencyProperty.Register("GifSource", typeof(string), typeof(GifImage), new UIPropertyMetadata(string.Empty, GifSourcePropertyChanged));
73 | private static void GifSourcePropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
74 | {
75 | (sender as GifImage).Initialize();
76 | }
77 | ///
78 | /// Starts the animation
79 | ///
80 | public void StartAnimation()
81 | {
82 | if (!_isInitialized)
83 | this.Initialize();
84 |
85 | BeginAnimation(FrameIndexProperty, _animation);
86 | }
87 | ///
88 | /// Stops the animation
89 | ///
90 | public void StopAnimation()
91 | {
92 | BeginAnimation(FrameIndexProperty, null);
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/RemoteUpdate/Global.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.ComponentModel;
3 | using System.Windows.Threading;
4 |
5 | namespace RemoteUpdate
6 | {
7 | static class Global
8 | {
9 | // Table for App Settings
10 | public static System.Data.DataTable TableSettings = new System.Data.DataTable("Settings");
11 | // Table for Runtime values like Server, IP, Status from Ping and Uptime etc.
12 | public static System.Data.DataTable TableRuntime = new System.Data.DataTable("Runtime");
13 | // BackgroundWorker List for Uptime Checks
14 | public static List ListBackgroundWorkerUptime = new List();
15 | // BackgroundWorker List for Ping Checks
16 | public static List ListBackgroundWorkerPing = new List();
17 | // BackgroundWorker for Process Lookup
18 | public static BackgroundWorker BackgroundWorkerProcess = new BackgroundWorker();
19 | // Timer for Grid Update
20 | public static DispatcherTimer TimerUpdateGrid = new DispatcherTimer();
21 | // Culture variable, for future changes to dynamic adaption
22 | public static System.Globalization.CultureInfo cultures = System.Globalization.CultureInfo.CurrentCulture;
23 | // Variable for Logfile Destination
24 | public static string strLogFile = System.AppDomain.CurrentDomain.BaseDirectory + "RemoteUpdateLog-" + System.DateTime.Now.ToString("yyyy.MM.dd_HHmmss", cultures) + ".txt";
25 | // Bool for Log and Save Write
26 | public static bool bDirectoryWritable;
27 | // Streamwriter for LogFile
28 | public static System.IO.StreamWriter streamLogFile;
29 | // Logfile divide character
30 | public static string stringTab = System.Convert.ToChar(9).ToString(cultures);
31 | // Verbose Logging enabled?
32 | public static bool bVerboseLog = false;
33 | // IPHostEntry for localhost to check if servername is localhost
34 | public static System.Net.IPHostEntry localHost = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName());
35 | // Variable for threaded Update Search
36 | public static bool bNewVersionOnline = false;
37 | // TableScripts
38 | public static System.Data.DataTable TableScripts = new System.Data.DataTable("Scripts");
39 | // Password String
40 | public static string strDecryptionPassword = "";
41 |
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/RemoteUpdate/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/RemoteUpdate/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Threading;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Media;
7 | using System.Windows.Shapes;
8 |
9 | namespace RemoteUpdate
10 | {
11 | ///
12 | /// Interaction logic for MainWindow.xaml
13 | ///
14 | ///
15 | public partial class MainWindow : Window
16 | {
17 | // MainWindow Grid
18 | internal Grid GridMainWindow;
19 | public MainWindow()
20 | {
21 | InitializeComponent();
22 | if (!Tasks.CreateLogFile())
23 | {
24 | this.ButtonSave.IsEnabled = false;
25 | MessageBox.Show("Directory is not writable therefore no settings can be saved or log file can be written");
26 | }
27 | // Global.TableScripts Columns Creation
28 | Global.TableScripts.Columns.Add("Name");
29 | Global.TableScripts.Columns.Add("Script");
30 | // Global.TableRuntime Columns Creation
31 | Global.TableRuntime.Columns.Add("Servername");
32 | Global.TableRuntime.Columns.Add("IP");
33 | Global.TableRuntime.Columns.Add("Username");
34 | Global.TableRuntime.Columns.Add("Password");
35 | Global.TableRuntime.Columns.Add("Ping");
36 | Global.TableRuntime.Columns.Add("Uptime");
37 | Global.TableRuntime.Columns.Add("PID");
38 | // Get Grid to add more Controls
39 | GridMainWindow = this.Content as Grid;
40 | // Load Schema and Data from XML RemoteUpdateSettings.xml
41 | if (!Tasks.ReadXMLToTable(AppDomain.CurrentDomain.BaseDirectory + "RemoteUpdateSettings.xml", Global.TableSettings))
42 | {
43 | Global.TableSettings.Columns.Add("SMTPServer");
44 | Global.TableSettings.Columns.Add("SMTPPort");
45 | Global.TableSettings.Columns.Add("MailFrom");
46 | Global.TableSettings.Columns.Add("MailTo");
47 | Global.TableSettings.Columns.Add("PSVirtualAccountName");
48 | Global.TableSettings.Columns.Add("PSWUCommands");
49 | Global.TableSettings.Columns.Add("VerboseLog");
50 | Global.TableSettings.Rows.Add(Global.TableSettings.NewRow());
51 | Global.TableSettings.Rows[0]["PSVirtualAccountName"] = "VirtualAccount";
52 | }
53 | // Set Verbose Logging if it is true in Settings file
54 | bool bVerboseLog = bool.TryParse(Global.TableSettings.Rows[0]["VerboseLog"].ToString(), out bool bParse);
55 | if (bParse)
56 | {
57 | Global.bVerboseLog = bVerboseLog;
58 | }
59 | // Initialize Datatable for XML Load
60 | System.Data.DataTable LoadTable = new System.Data.DataTable();
61 | // Initialize Servernumber
62 | int ServerNumber;
63 | // Load Schema and Data from XML RemoteUpdateServer.xml
64 | bool bReadXML = Tasks.ReadXMLToTable(AppDomain.CurrentDomain.BaseDirectory + "RemoteUpdateServer.xml", LoadTable);
65 | // Only if Load of XML was successfull and RowCount is at least 1
66 | if (bReadXML == true && LoadTable.Rows.Count > 0)
67 | {
68 | // Temporary bool if Encryption Password is needed
69 | bool bPassword = false;
70 | // Check if in any Row is a saved Password, if yes, ask for the Password to encrypt
71 | for (int ii = 0; ii < LoadTable.Rows.Count; ii++)
72 | {
73 | if (LoadTable.Rows[ii]["Password"].ToString().Length > 0)
74 | {
75 | bPassword = true;
76 | break;
77 | }
78 | }
79 | if (bPassword)
80 | {
81 | GetPassword(false, out Global.strDecryptionPassword);
82 | }
83 |
84 | // Set Servernumber according to Rows from XML
85 | ServerNumber = LoadTable.Rows.Count;
86 | // Set Values for first Row
87 | this.TextBoxServer_0.Text = LoadTable.Rows[0]["Server"].ToString();
88 | this.CheckboxAccept_0.IsChecked = Convert.ToBoolean(LoadTable.Rows[0]["Accept"], Global.cultures);
89 | this.CheckboxDrivers_0.IsChecked = Convert.ToBoolean(LoadTable.Rows[0]["Drivers"], Global.cultures);
90 | this.CheckboxReboot_0.IsChecked = Convert.ToBoolean(LoadTable.Rows[0]["Reboot"], Global.cultures);
91 | this.CheckboxGUI_0.IsChecked = Convert.ToBoolean(LoadTable.Rows[0]["GUI"], Global.cultures);
92 | this.CheckboxMail_0.IsChecked = Convert.ToBoolean(LoadTable.Rows[0]["Mail"], Global.cultures);
93 | this.CheckboxEnabled_0.IsChecked = Convert.ToBoolean(LoadTable.Rows[0]["Enabled"], Global.cultures);
94 | // Create first DataRow in Global.TableRuntime
95 | System.Data.DataRow dtrow = Global.TableRuntime.NewRow();
96 | dtrow["Servername"] = LoadTable.Rows[0]["Server"].ToString();
97 | dtrow["IP"] = Tasks.GetIPfromHostname(LoadTable.Rows[0]["Server"].ToString());
98 | dtrow["Username"] = LoadTable.Rows[0]["Username"].ToString();
99 | dtrow["Password"] = Tasks.Decrypt(LoadTable.Rows[0]["Password"].ToString(), LoadTable.Rows[0]["Server"].ToString());
100 | dtrow["Ping"] = "";
101 | dtrow["Uptime"] = "";
102 | Global.TableRuntime.Rows.Add(dtrow);
103 | Tasks.WriteLogFile(0, "Row 1 filled with values", true);
104 | }
105 | else
106 | {
107 | // If no XML could be read, set the Servernumber to 0
108 | ServerNumber = 0;
109 | // Create Empty Data Row
110 | Global.TableRuntime.Rows.Add(Global.TableRuntime.NewRow());
111 | Tasks.WriteLogFile(0, "Empty row 1 created", true);
112 | }
113 | // Create BackgroundWorker (Ping and Uptime)
114 | Worker.CreateBackgroundWorker(0);
115 | // Change Height of Main Window when more than 10 Servers are in the List
116 | if (ServerNumber > 2) { Application.Current.MainWindow.Height = 170 + ServerNumber * 30; }
117 | // Add Controls for each Server loaded
118 | for (int ii = 1; ii < ServerNumber + 1; ii++)
119 | {
120 | // ServerName Textbox creation
121 | string tmpText = "";
122 | bool tmpBool = false;
123 | bool tmpBoolGUI = true;
124 | if (ii < ServerNumber) { tmpText = LoadTable.Rows[ii]["Server"].ToString(); }
125 | // Textbox Servername creation
126 | CreateTextbox("TextBoxServer_" + ii, tmpText, 18, 120, 20, 30 * (ii + 1));
127 | // Uptime Label creation
128 | CreateLabel("LabelUptime_" + ii, "", 26, 90, 150, 30 * (ii + 1) - 4, Visibility.Visible);
129 | // Accept Checkbox creation
130 | if (ii < ServerNumber) { tmpBool = Convert.ToBoolean(LoadTable.Rows[ii]["Accept"], Global.cultures); }
131 | CreateCheckbox("CheckboxAccept_" + ii, 250, 30 * (ii + 1), tmpBool);
132 | // Drivers Checkbox creation
133 | if (ii < ServerNumber) { tmpBool = Convert.ToBoolean(LoadTable.Rows[ii]["Drivers"], Global.cultures); }
134 | CreateCheckbox("CheckboxDrivers_" + ii, 310, 30 * (ii + 1), tmpBool);
135 | // Reboot Checkbox creation
136 | if (ii < ServerNumber) { tmpBool = Convert.ToBoolean(LoadTable.Rows[ii]["Reboot"], Global.cultures); }
137 | CreateCheckbox("CheckboxReboot_" + ii, 370, 30 * (ii + 1), tmpBool);
138 | // GUI Checkbox creation
139 | if (ii < ServerNumber) { tmpBoolGUI = Convert.ToBoolean(LoadTable.Rows[ii]["GUI"], Global.cultures); }
140 | CreateCheckbox("CheckboxGUI_" + ii, 430, 30 * (ii + 1), tmpBoolGUI);
141 | // Mail Checkbox creation
142 | if (ii < ServerNumber) { tmpBool = Convert.ToBoolean(LoadTable.Rows[ii]["Mail"], Global.cultures); }
143 | CreateCheckbox("CheckboxMail_" + ii, 490, 30 * (ii + 1), tmpBool);
144 | // Credentials Button creation
145 | CreateButton("ButtonCredentials_" + ii, "Credentials", 70, 530, 30 * ((ii + 1) - 1) + 29, new RoutedEventHandler(GetCredentials), System.Windows.Visibility.Visible);
146 | // Start Button creation
147 | CreateButton("ButtonStart_" + ii, "Update", 70, 620, 30 * ((ii + 1) - 1) + 29, new RoutedEventHandler(ButtonStartClick), System.Windows.Visibility.Visible);
148 | // Time Button creation
149 | CreateButton("ButtonTime_" + ii, "12:12:12", 70, 620, 30 * ((ii + 1) - 1) + 29, new RoutedEventHandler(ButtonTime_Click), System.Windows.Visibility.Hidden);
150 | // ComboBox creation
151 | CreateComboBox("ComboBox_" + ii, 620, 30 * ((ii + 1) - 1) + 29, new SelectionChangedEventHandler(ComboBox_SelectionChanged));
152 | // Enabled Checkbox creation
153 | if (ii < ServerNumber) { tmpBool = Convert.ToBoolean(LoadTable.Rows[ii]["Enabled"], Global.cultures); }
154 | CreateCheckbox("CheckboxEnabled_" + ii, 740, 30 * (ii + 1), tmpBool);
155 | // If Servernumber is Even, create Light Grey Rectangle Background
156 | if ((ii + 1) % 2 == 0)
157 | {
158 | // Light Grey Rectangle creation
159 | CreateRectangle("BackgroundRectangle_" + ii, 30, double.NaN, 0, 24 + 30 * ii, new SolidColorBrush(Color.FromRgb(222, 217, 217)), 0);
160 | CreateGifImage("gifImage_" + ii, 710, 30 * ((ii + 1) - 1) + 29);
161 | }
162 | else
163 | {
164 | CreateGifImage("gifImage_" + ii, 710, 30 * ((ii + 1) - 1) + 29);
165 | }
166 | // Create new Row in TableRuntime
167 | System.Data.DataRow dtrow = Global.TableRuntime.NewRow();
168 | if (ii < LoadTable.Rows.Count)
169 | {
170 | dtrow["Servername"] = LoadTable.Rows[ii]["Server"].ToString();
171 | dtrow["IP"] = Tasks.GetIPfromHostname(LoadTable.Rows[ii]["Server"].ToString());
172 | dtrow["Username"] = LoadTable.Rows[ii]["Username"].ToString();
173 | dtrow["Password"] = Tasks.Decrypt(LoadTable.Rows[ii]["Password"].ToString(), LoadTable.Rows[ii]["Server"].ToString());
174 | dtrow["Ping"] = "";
175 | dtrow["Uptime"] = "";
176 | }
177 | Global.TableRuntime.Rows.Add(dtrow);
178 | // Write Verbose Log
179 | Tasks.WriteLogFile(0, "Row " + (ii + 1) + " filled with values", true);
180 | // Create BackgroundWorker (Ping and Uptime)
181 | Worker.CreateBackgroundWorker(ii);
182 | }
183 | LoadTable.Dispose();
184 | // Timer Creation for Interface Updates
185 | Global.TimerUpdateGrid.Interval = TimeSpan.FromSeconds(5);
186 | Global.TimerUpdateGrid.Tick += (sender, e) => { Worker.TimerUpdateGrid_Tick(GridMainWindow); };
187 | Global.TimerUpdateGrid.Start();
188 | Tasks.WriteLogFile(0, "Timer for Grid Update created", true);
189 | // Check WinRM Status and write Info Message into Label
190 | SetWinRMStatus();
191 | Worker.CreateBackgroundWorkerProcess();
192 | new System.Threading.Tasks.Task(Tasks.CheckLatestVersion).Start();
193 | // Add Items to first and last Combobox
194 | ComboBox_0.ItemsSource = new System.Collections.Generic.List { "Update", "Pending", "Reboot", "Script" };
195 | ComboBox_All.ItemsSource = new System.Collections.Generic.List { "Update All", "Pending All", "Reboot All", "Script All" };
196 | }
197 | ///
198 | /// Function to change all Checkboxes IsChecked Status in the same name range
199 | ///
200 | ///
201 | ///
202 | private void CheckBoxChanged(object sender, RoutedEventArgs e)
203 | {
204 | var list = GridMainWindow.Children.OfType().Where(cb => cb.Name.Contains((sender as CheckBox).Name + "_")).ToArray();
205 | if (((CheckBox)sender).IsChecked == true)
206 | {
207 | for (int ii = 0; ii < list.Length; ii++)
208 | {
209 | list[ii].IsChecked = true;
210 | }
211 | }
212 | else
213 | {
214 | for (int ii = 0; ii < list.Length; ii++)
215 | {
216 | list[ii].IsChecked = false;
217 | }
218 | }
219 | }
220 | ///
221 | /// Function to Uncheck CheckboxAll if one Checkbox_? is unchecked
222 | ///
223 | ///
224 | ///
225 | private void CheckBoxChangedServer(object sender, RoutedEventArgs e)
226 | {
227 | string strCheckBoxName = (sender as CheckBox).Name.Split('_')[0];
228 | var list = GridMainWindow.Children.OfType().Where(cb => cb.Name == strCheckBoxName).FirstOrDefault();
229 | if (list.IsChecked == true)
230 | {
231 | list.Unchecked -= CheckBoxChanged;
232 | list.IsChecked = false;
233 | list.Unchecked += CheckBoxChanged;
234 | }
235 | }
236 | private void SaveSettings(object sender, EventArgs e)
237 | {
238 | bool bIsCredential = false;
239 | using (System.Data.DataTable SaveTable = new System.Data.DataTable("RemoteUpdateServer"))
240 | {
241 | SaveTable.Columns.Add("Server");
242 | SaveTable.Columns.Add("Accept");
243 | SaveTable.Columns.Add("Drivers");
244 | SaveTable.Columns.Add("Reboot");
245 | SaveTable.Columns.Add("GUI");
246 | SaveTable.Columns.Add("Mail");
247 | SaveTable.Columns.Add("Username");
248 | SaveTable.Columns.Add("Password");
249 | SaveTable.Columns.Add("Enabled");
250 | var tblist = GridMainWindow.Children.OfType().Where(tb => tb.Name.Contains("TextBoxServer_"));
251 | // Check if Credentials are there, if yes, then set bool to true
252 | for (int ii = 0; ii < tblist.Count(); ii++)
253 | {
254 | string tmpPassword = Global.TableRuntime.Rows[ii]["Password"].ToString();
255 | if (tmpPassword.Length > 0)
256 | {
257 | bIsCredential = true;
258 | break;
259 | }
260 | }
261 | // If bIsCredential is true, ask for password with which it should be saved
262 | string strEncryptionPassword = "";
263 | if (bIsCredential)
264 | {
265 | if (!GetPassword(true, out strEncryptionPassword))
266 | {
267 | return;
268 | }
269 | }
270 | // Create DataTable to write it to XML
271 | for (int ii = 0; ii < tblist.Count(); ii++)
272 | {
273 | string tmpServername = GridMainWindow.Children.OfType().Where(tb => tb.Name == "TextBoxServer_" + ii).FirstOrDefault().Text;
274 | string tmpPassword = Global.TableRuntime.Rows[ii]["Password"].ToString();
275 | if (tmpServername.Length == 0) { continue; }
276 | System.Data.DataRow dtrow = SaveTable.NewRow();
277 | dtrow["Server"] = tmpServername;
278 | dtrow["Accept"] = GridMainWindow.Children.OfType().Where(cb => cb.Name == "CheckboxAccept_" + ii).FirstOrDefault().IsChecked;
279 | dtrow["Drivers"] = GridMainWindow.Children.OfType().Where(cb => cb.Name == "CheckboxDrivers_" + ii).FirstOrDefault().IsChecked;
280 | dtrow["Reboot"] = GridMainWindow.Children.OfType().Where(cb => cb.Name == "CheckboxReboot_" + ii).FirstOrDefault().IsChecked;
281 | dtrow["GUI"] = GridMainWindow.Children.OfType().Where(cb => cb.Name == "CheckboxGUI_" + ii).FirstOrDefault().IsChecked;
282 | dtrow["Mail"] = GridMainWindow.Children.OfType().Where(cb => cb.Name == "CheckboxMail_" + ii).FirstOrDefault().IsChecked;
283 | dtrow["Username"] = Global.TableRuntime.Rows[ii]["Username"].ToString();
284 | if (strEncryptionPassword.Length > 0)
285 | {
286 | dtrow["Password"] = Tasks.Encrypt(Global.TableRuntime.Rows[ii]["Password"].ToString(), tmpServername, strEncryptionPassword);
287 | }
288 | else
289 | {
290 | dtrow["Password"] = "";
291 | }
292 | dtrow["Enabled"] = GridMainWindow.Children.OfType().Where(cb => cb.Name == "CheckboxEnabled_" + ii).FirstOrDefault().IsChecked;
293 | SaveTable.Rows.Add(dtrow);
294 | }
295 | Tasks.WriteTableToXML(SaveTable, System.AppDomain.CurrentDomain.BaseDirectory + "RemoteUpdateServer.xml");
296 | }
297 | Tasks.WriteTableToXML(Global.TableSettings, System.AppDomain.CurrentDomain.BaseDirectory + "RemoteUpdateSettings.xml");
298 | }
299 | private void CreateTextbox(string tbname, string tbtext, int tbheight, int tbwidth, int tbmarginleft, int tbmargintop)
300 | {
301 | TextBox Textbox1 = new TextBox()
302 | {
303 | Height = tbheight,
304 | Width = tbwidth,
305 | Name = tbname,
306 | Text = tbtext,
307 | HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
308 | VerticalAlignment = System.Windows.VerticalAlignment.Top,
309 | Margin = new Thickness(tbmarginleft, tbmargintop, 0, 0),
310 | TextWrapping = System.Windows.TextWrapping.NoWrap
311 | };
312 | Textbox1.LostFocus += TextboxLostFocus;
313 | GridMainWindow.Children.Add(Textbox1);
314 | }
315 | private void CreateLabel(string lblname, string lblContent, int lblheight, int lblwidth, int lblmarginleft, int lblmargintop, Visibility lblvisibility)
316 | {
317 | Label Label1 = new Label()
318 | {
319 | Height = lblheight,
320 | Width = lblwidth,
321 | Name = lblname,
322 | Content = lblContent,
323 | HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
324 | VerticalAlignment = System.Windows.VerticalAlignment.Top,
325 | Margin = new Thickness(lblmarginleft, lblmargintop, 0, 0),
326 | Visibility = lblvisibility,
327 | };
328 | GridMainWindow.Children.Add(Label1);
329 | }
330 | private void CreateCheckbox(string cbname, int cbmarginleft, int cbmargintop, bool cbchecked)
331 | {
332 | CheckBox CheckBox1 = new CheckBox()
333 | {
334 | Name = cbname,
335 | IsChecked = cbchecked,
336 | HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
337 | VerticalAlignment = System.Windows.VerticalAlignment.Top,
338 | Margin = new Thickness(cbmarginleft, cbmargintop, 0, 0),
339 | };
340 | if (cbname.StartsWith("CheckboxAccept_", StringComparison.Ordinal) || cbname.StartsWith("CheckboxGUI_", StringComparison.Ordinal))
341 | {
342 | CheckBox1.Checked += CheckboxChangedGUIAccept;
343 | CheckBox1.Unchecked += CheckboxChangedGUIAccept;
344 | }
345 | else
346 | {
347 | CheckBox1.Unchecked += CheckBoxChangedServer;
348 | }
349 | GridMainWindow.Children.Add(CheckBox1);
350 | }
351 | private void CreateButton(string btnname, string btntext, int btnwidth, int btnmarginleft, int rtmargintop, RoutedEventHandler btnevent, System.Windows.Visibility btnvisibility)
352 | {
353 | Button Button1 = new Button()
354 | {
355 | Name = btnname,
356 | Width = btnwidth,
357 | Content = btntext,
358 | HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
359 | VerticalAlignment = System.Windows.VerticalAlignment.Top,
360 | Margin = new Thickness(btnmarginleft, rtmargintop, 0, 0),
361 | Visibility = btnvisibility
362 | };
363 | Button1.Click += btnevent;
364 | GridMainWindow.Children.Add(Button1);
365 | }
366 | private void CreateRectangle(string rtname, int rtheight, double rtwidth, int rtmarginleft, int rtmargintop, SolidColorBrush rtfill, int rtstroke)
367 | {
368 | Rectangle Rectangle1 = new Rectangle()
369 | {
370 | Name = rtname,
371 | HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
372 | VerticalAlignment = System.Windows.VerticalAlignment.Top,
373 | Height = rtheight,
374 | Width = rtwidth,
375 | Margin = new Thickness(rtmarginleft, rtmargintop, 0, 0),
376 | Fill = rtfill,
377 | StrokeThickness = rtstroke,
378 | };
379 | Panel.SetZIndex(Rectangle1, -3);
380 | GridMainWindow.Children.Add(Rectangle1);
381 | }
382 | private void CreateGifImage(string strname, int imarginleft, int imargintop)
383 | {
384 | GifImage GifImage1 = new GifImage()
385 | {
386 | Name = strname,
387 | HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
388 | VerticalAlignment = System.Windows.VerticalAlignment.Top,
389 | Width = 20,
390 | Height = 20,
391 | Margin = new Thickness(imarginleft, imargintop, 0, 0),
392 | AutoStart = false,
393 | Visibility = Visibility.Hidden
394 | };
395 | GridMainWindow.Children.Add(GifImage1);
396 | }
397 | private void CreateComboBox(string strname, int imarginleft, int imargintop, SelectionChangedEventHandler btnevent)
398 | {
399 | ComboBox ComboBox1 = new ComboBox()
400 | {
401 | Name = strname,
402 | HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
403 | VerticalAlignment = System.Windows.VerticalAlignment.Top,
404 | Width = 88,
405 | Height = 20,
406 | Margin = new Thickness(imarginleft, imargintop, 0, 0)
407 | // Panel.ZIndex="-1"
408 | };
409 | Panel.SetZIndex(ComboBox1, -1);
410 | ComboBox1.ItemsSource = new System.Collections.Generic.List { "Update", "Pending", "Reboot", "Script" };
411 | ComboBox1.SelectionChanged += btnevent;
412 | GridMainWindow.Children.Add(ComboBox1);
413 | }
414 | ///
415 | /// Event Function that calls two functions for Textbox LostFocus Handling
416 | ///
417 | ///
418 | ///
419 | private void TextboxLostFocus(object sender, RoutedEventArgs e)
420 | {
421 | int line = Int32.Parse((sender as TextBox).Name.Split('_')[1], Global.cultures);
422 | (sender as TextBox).Text = (sender as TextBox).Text.Trim();
423 | Tasks.LockAndWriteDataTable(Global.TableRuntime, line, "IP", Tasks.GetIPfromHostname((sender as TextBox).Text), 100);
424 | //Global.TableRuntime.Rows[line]["IP"] = Tasks.GetIPfromHostname((sender as TextBox).Text);
425 | Tasks.LockAndWriteDataTable(Global.TableRuntime, line, "Servername", (sender as TextBox).Text, 100);
426 | //Global.TableRuntime.Rows[line]["Servername"] = (sender as TextBox).Text;
427 | CreateNewLine(sender, e);
428 | }
429 | ///
430 | /// Creates a new Line of Controls when it is the last one
431 | ///
432 | ///
433 | ///
434 | private void CreateNewLine(object sender, RoutedEventArgs e)
435 | {
436 | TextBox tborigin = sender as TextBox;
437 | if (tborigin.Text.Length == 0) { return; }
438 | var list = GridMainWindow.Children.OfType().Where(tb => tb.Name.Contains((sender as TextBox).Name.Split('_')[0])).ToArray();
439 | // Compare the sender and the last element if the Textbox Name is the same
440 | if (tborigin.Name == list[list.Length - 1].Name)
441 | {
442 | // Textbox Servername creation
443 | CreateTextbox("TextBoxServer_" + list.Length, "", 18, 120, 20, 30 * (list.Length + 1));
444 | // Uptime Label creation
445 | CreateLabel("LabelUptime_" + list.Length, "", 26, 90, 150, 30 * (list.Length + 1) - 4, Visibility.Visible);
446 | // Accept Checkbox creation
447 | CreateCheckbox("CheckboxAccept_" + list.Length, 250, 30 * (list.Length + 1), false);
448 | // Drivers Checkbox creation
449 | CreateCheckbox("CheckboxDrivers_" + list.Length, 310, 30 * (list.Length + 1), false);
450 | // Reboot Checkbox creation
451 | CreateCheckbox("CheckboxReboot_" + list.Length, 370, 30 * (list.Length + 1), false);
452 | // GUI Checkbox creation
453 | CreateCheckbox("CheckboxGUI_" + list.Length, 430, 30 * (list.Length + 1), true);
454 | // Mail Checkbox creation
455 | CreateCheckbox("CheckboxMail_" + list.Length, 490, 30 * (list.Length + 1), false);
456 | // Credentials Button creation
457 | CreateButton("ButtonCredentials_" + list.Length, "Credentials", 70, 530, 30 * ((list.Length + 1) - 1) + 29, new RoutedEventHandler(GetCredentials), System.Windows.Visibility.Visible);
458 | // Start Button creation
459 | CreateButton("ButtonStart_" + list.Length, "Update", 70, 620, 30 * ((list.Length + 1) - 1) + 29, new RoutedEventHandler(ButtonStartClick), System.Windows.Visibility.Visible);
460 | // Time Button creation
461 | CreateButton("ButtonTime_" + list.Length, "12:12:12", 70, 620, 30 * ((list.Length + 1) - 1) + 29, new RoutedEventHandler(ButtonTime_Click), System.Windows.Visibility.Hidden);
462 | // ComboBox creation
463 | CreateComboBox("ComboBox_" + list.Length, 620, 30 * ((list.Length + 1) - 1) + 29, new SelectionChangedEventHandler(ComboBox_SelectionChanged));
464 | // Enabled Checkbox creation
465 | CreateCheckbox("CheckboxEnabled_" + list.Length, 740, 30 * (list.Length + 1), false);
466 | if ((list.Length + 1) % 2 == 0)
467 | {
468 | // Light Grey Rectangle creation
469 | CreateRectangle("BackgroundRectangle_" + list.Length, 30, double.NaN, 0, 24 + 30 * list.Length, new SolidColorBrush(Color.FromRgb(222, 217, 217)), 0);
470 | CreateGifImage("gifImage_" + list.Length, 710, 30 * ((list.Length + 1) - 1) + 29);
471 | }
472 | else
473 | {
474 | CreateGifImage("gifImage_" + list.Length, 710, 30 * ((list.Length + 1) - 1) + 29);
475 | }
476 | Worker.CreateBackgroundWorker(list.Length);
477 | if (list.Length >= 3)
478 | {
479 | Application.Current.MainWindow.Height = 170 + list.Length * 30;
480 | }
481 | System.Data.DataRow dtrow = Global.TableRuntime.NewRow();
482 | dtrow["Servername"] = "";
483 | dtrow["IP"] = "";
484 | dtrow["Username"] = "";
485 | dtrow["Password"] = "";
486 | Global.TableRuntime.Rows.Add(dtrow);
487 | }
488 | }
489 | private void GetCredentials(object sender, RoutedEventArgs e)
490 | {
491 | int iLabelID = Int32.Parse((sender as Button).Name.Split('_')[1], Global.cultures);
492 | string tmpServer = Global.TableRuntime.Rows[iLabelID]["Servername"].ToString().ToUpper(Global.cultures);
493 | Credentials AskCred = new Credentials(iLabelID);
494 | AskCred.Title = tmpServer + " Credentials";
495 | AskCred.ShowDialog();
496 | }
497 | private bool GetPassword(bool bEncrypt, out string strCryptPassword)
498 | {
499 | Password AskPassword = new Password(bEncrypt);
500 | if ((bool)AskPassword.ShowDialog())
501 | {
502 | strCryptPassword = AskPassword.PasswordBoxPassword.Password.ToString(Global.cultures);
503 | return true;
504 | }
505 | else
506 | {
507 | strCryptPassword = "";
508 | return false;
509 | }
510 | }
511 | private void StartUpdate(int line)
512 | {
513 | if (Tasks.CheckPSConnection(line))
514 | {
515 | Tasks.OpenPowerShellUpdate(line, GridMainWindow);
516 | }
517 | else
518 | {
519 | string strFailureMessage;
520 | if (Tasks.CreatePSConnectionPrerequisites(line, out strFailureMessage))
521 | {
522 | Tasks.OpenPowerShellUpdate(line, GridMainWindow);
523 | }
524 | else
525 | {
526 | ThreadPool.QueueUserWorkItem(delegate { MessageBox.Show("Can't connect to server " + Global.TableRuntime.Rows[line]["Servername"].ToString().ToUpper(Global.cultures) + ".\nPlease check your credentials, firewall ruleset and the WinRM settings."); });
527 | Tasks.LockAndWriteDataTable(Global.TableRuntime, line, "PID", "error", 100);
528 | Tasks.UpdateStatusGUI(line, "error", GridMainWindow);
529 | }
530 | }
531 | }
532 | private void StartPending(int line)
533 | {
534 | if (Tasks.CheckPSConnection(line))
535 | {
536 | Tasks.AskPendingStatus(line, GridMainWindow);
537 | }
538 | else
539 | {
540 | string strFailureMessage;
541 | if (Tasks.CreatePSConnectionPrerequisites(line, out strFailureMessage))
542 | {
543 | Tasks.AskPendingStatus(line, GridMainWindow);
544 | }
545 | else
546 | {
547 | ThreadPool.QueueUserWorkItem(delegate { MessageBox.Show("Can't connect to server " + Global.TableRuntime.Rows[line]["Servername"].ToString().ToUpper(Global.cultures) + ".\nPlease check your credentials, firewall ruleset and the WinRM settings."); });
548 | Tasks.UpdateStatusGUI(line, "error", GridMainWindow);
549 | }
550 | }
551 | }
552 |
553 | private void ButtonStart_Click(object sender, RoutedEventArgs e)
554 | {
555 | int line = Int32.Parse((sender as Button).Name.Split('_')[1], Global.cultures);
556 | ButtonClicked(line);
557 | }
558 | private void ButtonTime_Click(object sender, RoutedEventArgs e)
559 | {
560 | HideTime(Int32.Parse((sender as Button).Name.Split('_')[1], Global.cultures));
561 | }
562 |
563 | private void ButtonStartAll_Click(object sender, RoutedEventArgs e)
564 | {
565 | string btnContent = GridMainWindow.Children.OfType