Guest User

Untitled

a guest
Jun 8th, 2026
14
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.51 KB | None | 0 0
  1. $ErrorActionPreference = "Stop"
  2.  
  3. # Confirm Administrator rights.
  4. $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
  5. $principal = New-Object Security.Principal.WindowsPrincipal($identity)
  6.  
  7. if (-not $principal.IsInRole(
  8. [Security.Principal.WindowsBuiltInRole]::Administrator
  9. )) {
  10. Write-Host ""
  11. Write-Host "Open Windows PowerShell as Administrator, then paste this again." `
  12. -ForegroundColor Red
  13. return
  14. }
  15.  
  16. Add-Type -AssemblyName System.Drawing
  17. Add-Type -AssemblyName System.Windows.Forms
  18.  
  19. $DeployRoot = "C:\Deploy\TrayTime"
  20. $LogDir = Join-Path $DeployRoot "log"
  21. $InstallDir = "C:\ProgramData\TrayTime"
  22.  
  23. $SourceFile = Join-Path $DeployRoot "TrayTime.cs"
  24. $DeployIcon = Join-Path $DeployRoot "TrayTime.ico"
  25. $DeployExe = Join-Path $DeployRoot "TrayTime.exe"
  26.  
  27. $InstalledExe = Join-Path $InstallDir "TrayTime.exe"
  28. $InstalledIcon = Join-Path $InstallDir "TrayTime.ico"
  29.  
  30. $UninstallScript = Join-Path $DeployRoot "Uninstall-TrayTime.ps1"
  31.  
  32. $StartMenuFolder = Join-Path `
  33. $env:ProgramData `
  34. "Microsoft\Windows\Start Menu\Programs\TrayTime"
  35.  
  36. $Stamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
  37. $LogFile = Join-Path $LogDir "TrayTime_Install_$Stamp.log"
  38.  
  39. New-Item -ItemType Directory -Path $DeployRoot -Force | Out-Null
  40. New-Item -ItemType Directory -Path $LogDir -Force | Out-Null
  41. New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
  42. New-Item -ItemType Directory -Path $StartMenuFolder -Force | Out-Null
  43.  
  44. Start-Transcript -Path $LogFile -Force
  45.  
  46. try {
  47. Write-Host ""
  48. Write-Host "Installing TrayTime..." -ForegroundColor Cyan
  49. Write-Host "Started: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
  50. Write-Host "Computer: $env:COMPUTERNAME"
  51.  
  52. # Stop an older running version before replacing it.
  53. Get-Process TrayTime -ErrorAction SilentlyContinue |
  54. Stop-Process -Force -ErrorAction SilentlyContinue
  55.  
  56. # Remove older per-user shortcuts and startup entries.
  57. Remove-ItemProperty `
  58. -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" `
  59. -Name "TrayTime" `
  60. -ErrorAction SilentlyContinue
  61.  
  62. $OldUserStartMenu = Join-Path `
  63. ([Environment]::GetFolderPath("Programs")) `
  64. "TrayTime"
  65.  
  66. Remove-Item `
  67. -LiteralPath $OldUserStartMenu `
  68. -Recurse `
  69. -Force `
  70. -ErrorAction SilentlyContinue
  71.  
  72. $OldDesktopShortcut = Join-Path `
  73. ([Environment]::GetFolderPath("Desktop")) `
  74. "TrayTime.lnk"
  75.  
  76. Remove-Item `
  77. -LiteralPath $OldDesktopShortcut `
  78. -Force `
  79. -ErrorAction SilentlyContinue
  80.  
  81. # ------------------------------------------------------------
  82. # Create the dark-green circular icon with bold white T.
  83. # ------------------------------------------------------------
  84.  
  85. $bitmap = New-Object System.Drawing.Bitmap 64,64
  86.  
  87. $graphics = [System.Drawing.Graphics]::FromImage($bitmap)
  88. $graphics.SmoothingMode = `
  89. [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias
  90. $graphics.TextRenderingHint = `
  91. [System.Drawing.Text.TextRenderingHint]::AntiAliasGridFit
  92.  
  93. $graphics.Clear([System.Drawing.Color]::Transparent)
  94.  
  95. $circleBrush = New-Object System.Drawing.SolidBrush(
  96. [System.Drawing.Color]::FromArgb(255, 0, 85, 35)
  97. )
  98.  
  99. $letterBrush = New-Object System.Drawing.SolidBrush(
  100. [System.Drawing.Color]::White
  101. )
  102.  
  103. $font = New-Object System.Drawing.Font(
  104. "Arial",
  105. 40,
  106. [System.Drawing.FontStyle]::Bold,
  107. [System.Drawing.GraphicsUnit]::Pixel
  108. )
  109.  
  110. $format = New-Object System.Drawing.StringFormat
  111. $format.Alignment = [System.Drawing.StringAlignment]::Center
  112. $format.LineAlignment = [System.Drawing.StringAlignment]::Center
  113.  
  114. $graphics.FillEllipse(
  115. $circleBrush,
  116. 2,
  117. 2,
  118. 60,
  119. 60
  120. )
  121.  
  122. $graphics.DrawString(
  123. "T",
  124. $font,
  125. $letterBrush,
  126. (New-Object System.Drawing.RectangleF 0,0,64,61),
  127. $format
  128. )
  129.  
  130. $iconHandle = $bitmap.GetHicon()
  131. $icon = [System.Drawing.Icon]::FromHandle($iconHandle)
  132.  
  133. $iconStream = [System.IO.File]::Create($DeployIcon)
  134. $icon.Save($iconStream)
  135. $iconStream.Close()
  136.  
  137. $graphics.Dispose()
  138. $bitmap.Dispose()
  139. $circleBrush.Dispose()
  140. $letterBrush.Dispose()
  141. $font.Dispose()
  142. $format.Dispose()
  143.  
  144. Write-Host "Created icon: $DeployIcon"
  145.  
  146. # ------------------------------------------------------------
  147. # TrayTime application source.
  148. # ------------------------------------------------------------
  149.  
  150. $csharp = @'
  151. using System;
  152. using System.Drawing;
  153. using System.IO;
  154. using System.Threading;
  155. using System.Windows.Forms;
  156.  
  157. public static class TrayTimeProgram
  158. {
  159. private static NotifyIcon tray;
  160. private static ContextMenuStrip menu;
  161. private static ToolStripMenuItem[] dateItems;
  162. private static Mutex mutex;
  163.  
  164. [STAThread]
  165. public static void Main()
  166. {
  167. bool createdNew;
  168.  
  169. mutex = new Mutex(
  170. true,
  171. @"Global\TrayTime_SingleInstance",
  172. out createdNew
  173. );
  174.  
  175. if (!createdNew)
  176. {
  177. return;
  178. }
  179.  
  180. Application.EnableVisualStyles();
  181. Application.SetCompatibleTextRenderingDefault(false);
  182.  
  183. menu = new ContextMenuStrip();
  184. dateItems = new ToolStripMenuItem[4];
  185.  
  186. for (int i = 0; i < 4; i++)
  187. {
  188. ToolStripMenuItem item = new ToolStripMenuItem();
  189.  
  190. item.Click += delegate(object sender, EventArgs args)
  191. {
  192. ToolStripMenuItem clicked =
  193. (ToolStripMenuItem)sender;
  194.  
  195. string value =
  196. Convert.ToString(clicked.Tag);
  197.  
  198. if (!String.IsNullOrEmpty(value))
  199. {
  200. Clipboard.SetText(value);
  201.  
  202. tray.BalloonTipTitle =
  203. "Copied to clipboard";
  204.  
  205. tray.BalloonTipText = value;
  206. tray.ShowBalloonTip(900);
  207. }
  208. };
  209.  
  210. dateItems[i] = item;
  211. menu.Items.Add(item);
  212. }
  213.  
  214. menu.Items.Add(new ToolStripSeparator());
  215.  
  216. ToolStripMenuItem exitItem =
  217. new ToolStripMenuItem("Exit TrayTime");
  218.  
  219. exitItem.Click += delegate
  220. {
  221. tray.Visible = false;
  222. Application.Exit();
  223. };
  224.  
  225. menu.Items.Add(exitItem);
  226.  
  227. menu.Opening += delegate
  228. {
  229. UpdateMenu();
  230. };
  231.  
  232. tray = new NotifyIcon();
  233.  
  234. string iconPath = Path.Combine(
  235. AppDomain.CurrentDomain.BaseDirectory,
  236. "TrayTime.ico"
  237. );
  238.  
  239. if (File.Exists(iconPath))
  240. {
  241. tray.Icon = new Icon(iconPath);
  242. }
  243. else
  244. {
  245. tray.Icon = SystemIcons.Information;
  246. }
  247.  
  248. tray.Text =
  249. "TrayTime - click a date to copy";
  250.  
  251. tray.ContextMenuStrip = menu;
  252. tray.Visible = true;
  253.  
  254. // Left-click opens the same menu.
  255. // Right-click works through ContextMenuStrip.
  256. tray.MouseClick += delegate(
  257. object sender,
  258. MouseEventArgs args
  259. )
  260. {
  261. if (args.Button == MouseButtons.Left)
  262. {
  263. UpdateMenu();
  264. menu.Show(Cursor.Position);
  265. }
  266. };
  267.  
  268. // Double-click copies the longest format.
  269. tray.DoubleClick += delegate
  270. {
  271. string value = GetDateStrings()[3];
  272.  
  273. Clipboard.SetText(value);
  274.  
  275. tray.BalloonTipTitle =
  276. "Copied to clipboard";
  277.  
  278. tray.BalloonTipText = value;
  279. tray.ShowBalloonTip(900);
  280. };
  281.  
  282. try
  283. {
  284. Application.Run();
  285. }
  286. finally
  287. {
  288. tray.Visible = false;
  289. tray.Dispose();
  290. menu.Dispose();
  291.  
  292. try
  293. {
  294. mutex.ReleaseMutex();
  295. }
  296. catch
  297. {
  298. }
  299.  
  300. mutex.Dispose();
  301. }
  302. }
  303.  
  304. private static string[] GetDateStrings()
  305. {
  306. DateTime d = DateTime.Now;
  307.  
  308. string[] days =
  309. {
  310. "SUN",
  311. "MON",
  312. "TUE",
  313. "WED",
  314. "THUR",
  315. "FRI",
  316. "SAT"
  317. };
  318.  
  319. string[] months =
  320. {
  321. "JAN",
  322. "FEB",
  323. "MAR",
  324. "APR",
  325. "MAY",
  326. "JUN",
  327. "JUL",
  328. "AUG",
  329. "SEP",
  330. "OCT",
  331. "NOV",
  332. "DEC"
  333. };
  334.  
  335. string dow = days[(int)d.DayOfWeek];
  336. string month = months[d.Month - 1];
  337.  
  338. string date = String.Format(
  339. "{0}-{1}-{2}",
  340. d.Day,
  341. month,
  342. d.Year
  343. );
  344.  
  345. return new string[]
  346. {
  347. date,
  348.  
  349. String.Format(
  350. "{0}, {1}",
  351. dow,
  352. date
  353. ),
  354.  
  355. String.Format(
  356. "Day {0} - {1}, {2}",
  357. d.DayOfYear,
  358. dow,
  359. date
  360. ),
  361.  
  362. String.Format(
  363. "Day {0}: {1}, {2}",
  364. d.DayOfYear,
  365. dow,
  366. date
  367. )
  368. };
  369. }
  370.  
  371. private static void UpdateMenu()
  372. {
  373. string[] values = GetDateStrings();
  374.  
  375. for (int i = 0; i < dateItems.Length; i++)
  376. {
  377. dateItems[i].Text = values[i];
  378. dateItems[i].Tag = values[i];
  379. }
  380. }
  381. }
  382. '@
  383.  
  384. [System.IO.File]::WriteAllText(
  385. $SourceFile,
  386. $csharp,
  387. [System.Text.UTF8Encoding]::new($true)
  388. )
  389.  
  390. Remove-Item `
  391. -LiteralPath $DeployExe `
  392. -Force `
  393. -ErrorAction SilentlyContinue
  394.  
  395. Write-Host "Compiling TrayTime.exe..."
  396.  
  397. Add-Type `
  398. -TypeDefinition $csharp `
  399. -Language CSharp `
  400. -ReferencedAssemblies @(
  401. "System.dll",
  402. "System.Drawing.dll",
  403. "System.Windows.Forms.dll"
  404. ) `
  405. -OutputAssembly $DeployExe `
  406. -OutputType WindowsApplication
  407.  
  408. if (-not (Test-Path $DeployExe)) {
  409. throw "TrayTime.exe was not created."
  410. }
  411.  
  412. Copy-Item $DeployExe $InstalledExe -Force
  413. Copy-Item $DeployIcon $InstalledIcon -Force
  414.  
  415. Write-Host "Installed application: $InstalledExe"
  416.  
  417. # ------------------------------------------------------------
  418. # Start TrayTime for every user at sign-in.
  419. # ------------------------------------------------------------
  420.  
  421. $MachineRunKey = `
  422. "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run"
  423.  
  424. New-Item -Path $MachineRunKey -Force | Out-Null
  425.  
  426. New-ItemProperty `
  427. -Path $MachineRunKey `
  428. -Name "TrayTime" `
  429. -Value "`"$InstalledExe`"" `
  430. -PropertyType String `
  431. -Force | Out-Null
  432.  
  433. Write-Host "Added all-users startup entry."
  434.  
  435. # ------------------------------------------------------------
  436. # Create uninstaller.
  437. # ------------------------------------------------------------
  438.  
  439. $uninstallSource = @'
  440. $ErrorActionPreference = "SilentlyContinue"
  441.  
  442. $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
  443. $principal = New-Object Security.Principal.WindowsPrincipal($identity)
  444.  
  445. $isAdmin = $principal.IsInRole(
  446. [Security.Principal.WindowsBuiltInRole]::Administrator
  447. )
  448.  
  449. if (-not $isAdmin) {
  450. Start-Process powershell.exe `
  451. -Verb RunAs `
  452. -ArgumentList @(
  453. "-NoProfile",
  454. "-ExecutionPolicy",
  455. "Bypass",
  456. "-File",
  457. "`"$PSCommandPath`""
  458. )
  459.  
  460. exit
  461. }
  462.  
  463. Add-Type -AssemblyName System.Windows.Forms
  464.  
  465. Get-Process TrayTime -ErrorAction SilentlyContinue |
  466. Stop-Process -Force -ErrorAction SilentlyContinue
  467.  
  468. Remove-ItemProperty `
  469. -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" `
  470. -Name "TrayTime" `
  471. -ErrorAction SilentlyContinue
  472.  
  473. $StartMenuFolder = Join-Path `
  474. $env:ProgramData `
  475. "Microsoft\Windows\Start Menu\Programs\TrayTime"
  476.  
  477. $InstallDir = "C:\ProgramData\TrayTime"
  478.  
  479. Remove-Item `
  480. -LiteralPath $StartMenuFolder `
  481. -Recurse `
  482. -Force `
  483. -ErrorAction SilentlyContinue
  484.  
  485. Remove-Item `
  486. -LiteralPath $InstallDir `
  487. -Recurse `
  488. -Force `
  489. -ErrorAction SilentlyContinue
  490.  
  491. [System.Windows.Forms.MessageBox]::Show(
  492. "TrayTime was uninstalled.",
  493. "TrayTime",
  494. [System.Windows.Forms.MessageBoxButtons]::OK,
  495. [System.Windows.Forms.MessageBoxIcon]::Information
  496. ) | Out-Null
  497. '@
  498.  
  499. [System.IO.File]::WriteAllText(
  500. $UninstallScript,
  501. $uninstallSource,
  502. [System.Text.UTF8Encoding]::new($true)
  503. )
  504.  
  505. # ------------------------------------------------------------
  506. # Create Start Menu shortcuts for all users.
  507. # ------------------------------------------------------------
  508.  
  509. Remove-Item `
  510. -LiteralPath $StartMenuFolder `
  511. -Recurse `
  512. -Force `
  513. -ErrorAction SilentlyContinue
  514.  
  515. New-Item `
  516. -ItemType Directory `
  517. -Path $StartMenuFolder `
  518. -Force | Out-Null
  519.  
  520. $shell = New-Object -ComObject WScript.Shell
  521.  
  522. $OpenShortcut = Join-Path `
  523. $StartMenuFolder `
  524. "Open TrayTime.lnk"
  525.  
  526. $open = $shell.CreateShortcut($OpenShortcut)
  527. $open.TargetPath = $InstalledExe
  528. $open.WorkingDirectory = $InstallDir
  529. $open.IconLocation = $InstalledIcon
  530. $open.Description = "Open TrayTime"
  531. $open.Save()
  532.  
  533. $UninstallShortcut = Join-Path `
  534. $StartMenuFolder `
  535. "Uninstall TrayTime.lnk"
  536.  
  537. $remove = $shell.CreateShortcut($UninstallShortcut)
  538. $remove.TargetPath = "powershell.exe"
  539.  
  540. $remove.Arguments = (
  541. '-NoProfile -ExecutionPolicy Bypass -File "{0}"' `
  542. -f $UninstallScript
  543. )
  544.  
  545. $remove.WorkingDirectory = $DeployRoot
  546. $remove.IconLocation = $InstalledIcon
  547. $remove.Description = "Uninstall TrayTime"
  548. $remove.Save()
  549.  
  550. Write-Host "Created all-users Start Menu folder:"
  551. Write-Host $StartMenuFolder
  552.  
  553. # Ensure there is no desktop shortcut.
  554. $DesktopFolders = @(
  555. [Environment]::GetFolderPath("Desktop"),
  556. "$env:PUBLIC\Desktop"
  557. )
  558.  
  559. foreach ($DesktopFolder in $DesktopFolders) {
  560. if ($DesktopFolder) {
  561. Remove-Item `
  562. -LiteralPath (
  563. Join-Path $DesktopFolder "TrayTime.lnk"
  564. ) `
  565. -Force `
  566. -ErrorAction SilentlyContinue
  567. }
  568. }
  569.  
  570. # Start TrayTime now.
  571. Start-Process `
  572. -FilePath $InstalledExe `
  573. -WorkingDirectory $InstallDir
  574.  
  575. Start-Sleep -Seconds 2
  576.  
  577. $process = Get-Process TrayTime -ErrorAction SilentlyContinue
  578.  
  579. if (-not $process) {
  580. throw "TrayTime installed, but its process did not start."
  581. }
  582.  
  583. $hash = Get-FileHash `
  584. -LiteralPath $InstalledExe `
  585. -Algorithm SHA256
  586.  
  587. Write-Host ""
  588. Write-Host "TrayTime installed successfully." `
  589. -ForegroundColor Green
  590.  
  591. Write-Host "Application: $InstalledExe"
  592. Write-Host "Start Menu: TrayTime"
  593. Write-Host "Log: $LogFile"
  594. Write-Host "SHA256: $($hash.Hash)"
  595.  
  596. # Restart Explorer so the new Start Menu folder appears immediately.
  597. Write-Host "Refreshing Windows Explorer..."
  598.  
  599. Get-Process explorer -ErrorAction SilentlyContinue |
  600. Stop-Process -Force -ErrorAction SilentlyContinue
  601.  
  602. Start-Sleep -Seconds 1
  603. Start-Process explorer.exe
  604.  
  605. [System.Windows.Forms.MessageBox]::Show(
  606. "TrayTime installed successfully.`n`nStart Menu:`nTrayTime\Open TrayTime`nTrayTime\Uninstall TrayTime",
  607. "TrayTime Installed",
  608. [System.Windows.Forms.MessageBoxButtons]::OK,
  609. [System.Windows.Forms.MessageBoxIcon]::Information
  610. ) | Out-Null
  611. }
  612. catch {
  613. Write-Host ""
  614. Write-Host "TrayTime installation failed:" `
  615. -ForegroundColor Red
  616.  
  617. Write-Host $_.Exception.Message `
  618. -ForegroundColor Red
  619.  
  620. Write-Host "Log: $LogFile"
  621.  
  622. [System.Windows.Forms.MessageBox]::Show(
  623. "TrayTime installation failed.`n`n$($_.Exception.Message)`n`nLog:`n$LogFile",
  624. "TrayTime Installation Failed",
  625. [System.Windows.Forms.MessageBoxButtons]::OK,
  626. [System.Windows.Forms.MessageBoxIcon]::Error
  627. ) | Out-Null
  628. }
  629. finally {
  630. Stop-Transcript
  631. }
Add Comment
Please, Sign In to add comment