Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for airreglycmd.ps

(view source code of airreglycmd.ps as plain text)

  1. <#
  2. .SYNOPSIS
  3. Search a downloaded Lithuanian aircraft register database for an aircraft registation and if found, return the aircraft model
  4.  
  5. .DESCRIPTION
  6. First, create a subdirectory 'LY' in this script's parent folder.
  7. Next, download the Lithuanian aircraft register database (see links section), unzip it and move the PDF file to the 'LY' folder.
  8. Now run this script with an aircraft registration as its only parameter (see examples section).
  9. The script cannot read the PDF file directly, so the PDF file needs to be converted to plain text first.
  10. The script will look for a GhostScript installation on the computer, and if found, uses the following command to convert the PDF file to plain text:
  11.  
  12. "C:\Program Files\gs\gs<version>\bin\gswin64c.exe" -sDEVICE=txtwrite -o Lietuvos-Respublikoje-registruotu-orlaiviu-sarašas.txt Lietuvos-Respublikoje-registruotu-orlaiviu-sarašas.pdf
  13.  
  14. NOTE: If you download a new PDF file, make sure to either run this script with the -ConvertPDF switch or manually delete the old TEXT file!
  15.  
  16. The script will search for a line that starts with the registration.
  17. If a match is found, the model will be in the same line, more to the right.
  18. The script will display a tab-delimited string with the registration and the aircraft model (<registration><tab><tab><model>).
  19. If the script was started by another PowerShell script, the calling PowerShell script may also read the model from the variable $Model, passed on by this script.
  20. If the script was started by a batch file, the calling batch file can use 'FOR /F' on this PowerShell script's screen output to find the model.
  21. Get-Help './AirRegLYCmd.ps1' -Examples will show 2 examples of this script being called by another script.
  22.  
  23. .PARAMETER Registration
  24. A valid Lithuanian aircraft registration, i.e. LY-xxx (where each x is a single character)
  25.  
  26. .PARAMETER ConvertPDF
  27. Force conversion of the latest PDF file to plain text; use this switch once after downloading a new PDF file.
  28.  
  29. .PARAMETER Quiet
  30. Ignore all errors and do not display any error messages; in case of errors, just terminate with return code 1.
  31.  
  32. .PARAMETER Help
  33. Show the script's help screen
  34.  
  35. .PARAMETER Version
  36. Show this script's version number; if combined with -Verbose show full script path, version number and last/modified/release date
  37.  
  38. .PARAMETER Debug
  39. Show some progress messages
  40.  
  41. .OUTPUTS
  42. A tab-delimited string <registration><tab><tab><model> and model is also stored in output variable $Model.
  43.  
  44. .EXAMPLE
  45. . ./AirRegLYCmd.ps1 "LY-LAM"
  46. Will return tab-delimited string "LY-LAM<tab><tab>TIGER MOTH Replika", and set variable $Model to "TIGER MOTH Replika"
  47.  
  48. .EXAMPLE
  49. "LY-LAM" | . ./AirRegLYCmd.ps1
  50. Will also return tab-delimited string "LY-LAM<tab><tab>TIGER MOTH Replika", and set variable $Model to "TIGER MOTH Replika"
  51.  
  52. .EXAMPLE
  53. . ./AirRegLYCmd.ps1 "LY-LAM" -Debug
  54. This will return:
  55.  
  56. Started search for local database (text format) in folder ".\LY" at <date> <time>
  57. Start searching LY LAM in .\LY\Lietuvos-Respublikoje-registruotu-orlaiviu-sarašas.txt file at <date> <time>
  58. Found a match at <date> <time>
  59. LY-LAM          TIGER MOTH Replika
  60. Finished at <date> <time> (elapsed time <time elapsed>)
  61.  
  62. .EXAMPLE
  63. . ./AirRegLYCmd.ps1 -Version -Verbose
  64. Will return the full script path, version and last modified/release date
  65.  
  66. .EXAMPLE
  67. . ./AirRegLYCmd.ps1 -Version
  68. Will return the script version
  69.  
  70. .EXAMPLE
  71. Create and run the following PowerShell script:
  72. ===============================================================
  73. $Registration = 'OE-AKJ' ; $Manufacturer = '' ; $Model = ''
  74. [void] ( . "$PSScriptRoot\AirRegOECmd.ps1" -Registration $Registration )
  75. Write-Host ( "Registration : {0}`nManufacturer : {1}`nModel        : {2}" -f $Registration, $Manufacturer, $Model )
  76. ===============================================================
  77.  
  78. Besides setting variables $Manufacturer to "BOEING" and $Model to "E75", it will return:
  79.  
  80. Registration : LY-LAM
  81. Manufacturer :
  82. Model        : TIGER MOTH Replika
  83.  
  84. .EXAMPLE
  85. Create and run the following batch file:
  86. ===============================================================
  87. REM Note that there should only be a TAB and nothing else between delims= and the doublequote
  88. FOR /F "tokens=1-3 delims=	" %%A IN ('powershell . ./AirRegOECmd.ps1 OE-AKJ') DO (
  89. 	ECHO Registration : %%A
  90. 	ECHO Manufacturer :
  91. 	ECHO Model        : %%B
  92. )
  93. ===============================================================
  94.  
  95. It will return:
  96.  
  97. Registration : LY-LAM
  98. Manufacturer :
  99. Model        : TIGER MOTH Replika
  100.  
  101. .LINK
  102. Script written by Rob van der Woude:
  103. https://www.robvanderwoude.com/
  104.  
  105. .LINK
  106. Lithuanian aircraft register database:
  107. https://tka.lt/oro-transportas/katalogas/register-of-civil-aircraft-of-the-republic-of-lithuania/?lang=en
  108.  
  109. .LINK
  110. GhostScript download page:
  111. https://www.ghostscript.com/download/gsdnld.html
  112.  
  113. .LINK
  114. Convert PDF to text by user2176753 on StackOverflow.com:
  115. https://stackoverflow.com/a/26405241
  116.  
  117. .LINK
  118. Capture -Debug parameter by mklement0 on StackOverflow.com:
  119. https://stackoverflow.com/a/48643616
  120. #>
  121.  
  122. param (
  123. 	[parameter( ValueFromPipeline )]
  124. 	[ValidatePattern("(^\s*$|[\?/]|^LY-[A-Z]{3}$)")]
  125. 	[string]$Registration,
  126. 	[switch]$ConvertPDF,
  127. 	[switch]$Quiet,
  128. 	[switch]$Help,
  129. 	[switch]$Version
  130. )
  131.  
  132. $progver = "1.00"
  133.  
  134. $Registration = $Registration.ToUpper( )
  135. [string]$Manufacturer = ''
  136. [string]$Model = ''
  137. [bool]$Debug = ( $PSBoundParameters.ContainsKey( 'Debug' ) )
  138. [bool]$Verbose = ( $PSBoundParameters.ContainsKey( 'Verbose' ) )
  139.  
  140. if ( $Version ) {
  141. 	if ( $Verbose ) {
  142. 		$lastmod = ( [System.IO.File]::GetLastWriteTime( $PSCommandPath ) )
  143. 		if ( $lastmod.ToString( "h.mm" ) -eq $progver ) {
  144. 			"`"{0}`", Version {1}, release date {2}" -f $PSCommandPath, $progver, $lastmod.ToString( "yyyy-MM-dd" )
  145. 		} else {
  146. 			# if last modified time is not equal to program version, the script has been tampered with
  147. 			"`"{0}`", Version {1}, last modified date {2}" -f $PSCommandPath, $progver, $lastmod.ToString( "yyyy-MM-dd" )
  148. 		}
  149. 	} else {
  150. 		$progver
  151. 	}
  152. 	exit 0
  153. }
  154.  
  155. function ShowHelp( $errormessage = '' ) {
  156. 	if ( !$Quiet ) {
  157. 		Clear-Host
  158. 		if ( $errormessage ) {
  159. 			Write-Host
  160. 			Write-Host "Error: " -ForegroundColor Red -NoNewline
  161. 			Write-Host $errormessage
  162. 		}
  163. 		Write-Host
  164. 		Write-Host ( "`"{0}`", Version {1}" -f $PSCommandPath, $progver ) -NoNewline
  165. 		$lastmod = ( [System.IO.File]::GetLastWriteTime( $PSCommandPath ) )
  166. 		if ( $lastmod.ToString( "h.mm" ) -eq $progver ) {
  167. 			Write-Host ", release date " -NoNewline
  168. 		} else {
  169. 			# if last modified time is not equal to program version, the script has been tampered with
  170. 			Write-Host ", last modified date " -NoNewline
  171. 		}
  172. 		Write-Host $lastmod.ToString( "yyyy-MM-dd" )
  173. 		Write-Host
  174. 		Get-Help $PSCommandPath -Full
  175. 	}
  176. }
  177.  
  178. if ( $Help -or $Registration -match '(^\s*$|[\?/])' ) {
  179. 	ShowHelp
  180. 	exit 1
  181. }
  182.  
  183. function GetGhostscript( ) {
  184. 	# Check if GhostScript is installed, and if so, return the path to the command line execuatable
  185. 	$gskey = $null
  186. 	$gspath = ''
  187. 	$gsprog = ''
  188. 	if ( $Debug ) {
  189. 		Write-Host ( "Start searching the registry for GhostScript installations at {0}" -f ( Get-Date ) )
  190. 	}
  191. 	$gskey = ( ( Get-ChildItem -Path registry::'HKEY_LOCAL_MACHINE\SOFTWARE' -Recurse -Depth 2 -ErrorAction SilentlyContinue | Where-Object { $_.Name -match 'ghostscript' } | Select-Object -First 1 ) | Get-ChildItem | Sort-Object { [double]$_.PSChildName } | Select-Object -Last 1 ).Name
  192. 	if ( $gskey ) {
  193. 		if ( $Debug ) {
  194. 			Write-Host ( "Found GhostScript installation in the registry: `"{0}`" at {1}" -f $gskey, ( Get-Date ) )
  195. 		}
  196. 		$gspath = ( Get-ItemProperty -Path "Registry::$gskey" ).'(default)'
  197. 		if ( $gspath ) {
  198. 			if ( $Debug ) {
  199. 				Write-Host ( "Found GhostScript path in the registry: `"{0}`"" -f $gspath )
  200. 			}
  201. 			$gsprog = ( Get-ChildItem -Path "$gspath" -Filter 'gs*c.exe' -Recurse ).FullName
  202. 			if ( $Debug ) {
  203. 				Write-Host ( "Found GhostScript executable: `"{0}`"" -f $gsprog )
  204. 			}
  205. 		}
  206. 	}
  207. 	$gsprog
  208. }
  209.  
  210. function Convert-PDF2Text( [string]$pdffile, [string]$textfile = '' ) {
  211. 	if ( $Debug ) {
  212. 		Write-Host ( "Trying to convert downloaded PDF aircraft registry database file `"{0}`" to plain text at {1}" -f $pdffile, ( Get-Date ) )
  213. 		Write-Host "First, try and find GhostScript"
  214. 	}
  215. 	$gsexec = ( GetGhostScript )
  216. 	if ( [string]::IsNullOrWhiteSpace( $gsexec ) ) {
  217. 		if ( !$Quiet ) {
  218. 			Write-Host "GhostScript not found on this computer"
  219. 		}
  220. 		$false
  221. 	} else {
  222. 		if ( $Debug ) {
  223. 			Write-Host ( "GhostScript command line executable found: `"{0}`"" -f $gsexec )
  224. 		}
  225. 		if ( Test-Path -Path "$pdffile" -PathType 'Leaf' ) {
  226. 			if ( $Debug ) {
  227. 				Write-Host "PDF file found"
  228. 			}
  229. 			if ( [string]::IsNullOrWhiteSpace( $textfile ) ) {
  230. 				$parentfolder = [System.IO.Directory]::GetParent( $pdffile )
  231. 				$textfilename = [System.IO.Path]::GetFileNameWithoutExtension( $pdffile )
  232. 				$newtextfile = ( Join-Path -Path "$parentfolder" -ChildPath "$textfilename.txt" )
  233. 				$oldtextfile = ( Join-Path -Path "$parentfolder" -ChildPath "$textfilename.old" )
  234. 				if ( $Debug ) {
  235. 					Write-Host ( "New text file will be `"{0}`'" -f $newtextfile )
  236. 				}
  237. 				if ( Test-Path -Path "$newtextfile" -PathType 'Leaf' ) {
  238. 					if ( $debug ) {
  239. 						Write-Host "Text file already exist"
  240. 					}
  241. 					if ( Test-Path -Path $oldtextfile -PathType 'Leaf' ) {
  242. 						if ( $Debug ) {
  243. 							Write-Host ( "Deleting old text file `"{0}`"" -f $oldtextfile )
  244. 						}
  245. 						[System.IO.File]::Delete( $oldtextfile )
  246. 					}
  247. 					if ( $Debug ) {
  248. 						Write-Host ( "Renaming existing text file `"{0}`" to `"{1}`"" -f $newtextfile, $oldtextfile )
  249. 					}
  250. 					[System.IO.File]::Move( $newtextfile, $oldtextfile )
  251. 				}
  252. 			} else {
  253. 				$newtextfile = $textfile
  254. 				if ( $Debug ) {
  255. 					Write-Host ( "New text file will be `"{0}`'" -f $newtextfile )
  256. 				}
  257. 			}
  258. 			if ( $Debug ) {
  259. 				Write-Host ( "Actual conversion started at {0} using the command:" -f ( Get-Date ) )
  260. 				Write-Host "`"$gsexec`" -sDEVICE=txtwrite -o `"$newtextfile`" `"$pdffile`""
  261. 			}
  262. 			( . "$gsexec" -sDEVICE=txtwrite -o "$newtextfile" "$pdffile" )
  263. 			$true
  264. 		} else {
  265. 			if ( $Debug -or !$Quiet ) {
  266. 				Write-Host ( "Downloaded PDF aircraft registry database file `"{0}`" not found" -f $pdffile )
  267. 			}
  268. 			$false
  269. 		}
  270. 	}
  271. }
  272.  
  273. $LY_mark = $Registration.Substring( 3 )
  274.  
  275. $dbfile = ''
  276. $dbfolder = ( Join-Path -Path $PSScriptRoot -ChildPath 'LY' )
  277. if ( $Debug ) {
  278. 	$StopWatch = [System.Diagnostics.Stopwatch]::StartNew( )
  279. }
  280. if ( $ConvertPDF ) {
  281. 	$ErrorActionPreference = 'SilentlyContinue'
  282. 	$pdffile = ( Get-ChildItem -Path $dbfolder -Filter 'Lietuvos-*.pdf' | Sort-Object -Property 'Name' | Select-Object -Last 1 ).FullName
  283. 	$ErrorActionPreference = 'Continue'
  284. 	if ( $Debug ) {
  285. 		Write-Host "-ConvertPDF switch used, convert latest PDF to plain text first"
  286. 		Write-Host ( "Started search for local database (PDF format) in folder `"{0}`" at {1}" -f $dbfolder, ( Get-Date ) )
  287. 	}
  288. 	if ( Convert-PDF2Text $pdffile ) {
  289. 		$pdffilename = [System.IO.Path]::GetFileNameWithoutExtension( $pdffile )
  290. 		$dbfile = ( Join-Path -Path $dbfolder -ChildPath "$pdffilename.txt" )
  291. 	}
  292. } else {
  293. 	if ( $Debug ) {
  294. 		Write-Host ( "Started search for local database (text format) in folder `"{0}`" at {1}" -f $dbfolder, ( Get-Date ) )
  295. 	}
  296. 	$ErrorActionPreference = 'SilentlyContinue'
  297. 	$dbfile = ( Get-ChildItem -Path $dbfolder -Filter 'Lietuvos-*.txt' | Sort-Object -Property 'Name' | Select-Object -Last 1 ).FullName
  298. 	$ErrorActionPreference = 'Continue'
  299. }
  300. if ( [string]::IsNullOrWhiteSpace( $dbfile ) ) {
  301. 	if ( $Quiet -and !$Debug ) {
  302. 		exit 1
  303. 	} else {
  304. 		if ( $Debug ) {
  305. 			Write-Host "Converted text file not found, looking for original PDF aircraf registry database file"
  306. 		}
  307. 		$textfilename = [System.IO.Path]::GetFileNameWithoutExtension( $dbfile )
  308. 		$pdffile = ( Join-Path -Path $dbfolder -ChildPath "$textfilename.pdf" )
  309. 		if ( Test-Path $pdffile -PathType 'Leaf' ) {
  310. 			if ( $Debug ) {
  311. 				Write-Host ( "Founf PDF file `"{0}`"" -f $pdffile )
  312. 			}
  313. 			$message = "A PDF database file was found, but it needs to be converted to text for this script to function.`n`nDo you want to convert the PDF file to a plain text file now?"
  314. 			$title = "PDF to Text Conversion Required"
  315. 			$buttons = [System.Windows.Forms.MessageBoxButtons]::YesNo
  316. 			$answer = [System.Windows.Forms.MessageBox]::Show( $message, $title, $buttons )
  317. 			if ( $answer = 'Yes' ) {
  318. 				if ( Convert-PDF2Text $pdffile ) {
  319. 					if ( $Debug ) {
  320. 						Write-Host "PDF to text conversion completed"
  321. 					}
  322. 				} else {
  323. 					if ( $Debug -or !$Quiet ) {
  324. 						Write-Host "PDF to text conversion failed"
  325. 						exit 1
  326. 					}
  327. 				}
  328. 			} else {
  329. 				if ( $Debug -or !$Quiet ) {
  330. 					Write-Host "Please convert your PDF aircraft registry database file to plain text and try again"
  331. 				}
  332. 				exit 1
  333. 			}
  334. 		}
  335. 	}
  336. }
  337.  
  338. if ( $dbfile ) {
  339. 	if ( $Debug ) {
  340. 		Write-Host ( "Start searching LY {0} in {1} file at {2}" -f $LY_mark, $dbfile, ( Get-Date ) )
  341. 	}
  342. 	$found = $false
  343. 	( Get-Content -Path $dbfile ).Split( "`n" ) | ForEach-Object {
  344. 		if ( !$found ) {
  345. 			$pattern = "^\s{{11,17}}LY\s{{8,}}{0}\s" -f $LY_mark
  346. 			if ( $_ -match $pattern ) {
  347. 				if ( $Debug ) {
  348. 					Write-Host ( "Found a match at {0}" -f ( Get-Date ) )
  349. 				}
  350. 				$pattern = "[12][09]\d\d\.[01]\d\.[0-3]\d\s+(.*)"
  351. 				$Model = [System.Text.RegularExpressions.Regex]::Match( $_, $pattern ).Captures.Groups[1]
  352. 				if ( $Model -match "[12][09]\d\d\.[01]\d\.[0-3]\d\s*$" ) {
  353. 					$pattern = "(.*)[12][09]\d\d\.[01]\d\.[0-3]\d\s*$"
  354. 					$Model = [System.Text.RegularExpressions.Regex]::Match( $Model, $pattern ).Captures.Groups[1]
  355. 				}
  356. 				$Model = $Model.Trim( )
  357. 				# Remove the following words at the start of the line:
  358. 				# Dirižablis, Hidroplanas, Lektuvas, Malunsparnis, MKO, MKO/UL,
  359. 				# Motosklandytuvas, Motoskraidykle, Oro balionas, Sklandytuvas,
  360. 				# Sraigtasparnis, Ultralengvasis
  361. 				$pattern = "^(Diri.{1,2}ablis|Hidroplanas|L.{1,2}ktuvas|Mal.{1,2}nsparnis|MKO|MKO/UL|Motosklandytuvas|Motoskraidykl.{1,2}|Oro balionas|Sklandytuvas|Sraigtasparnis|Ultralengvasis)"
  362. 				$Model = [System.Text.RegularExpressions.Regex]::Replace( $Model, $pattern, "" )
  363. 				$Model = $Model.Trim( )
  364. 				# Remove text between parentheses from begin of model
  365. 				$pattern = "^\s*\([^\)]+\)\s*"
  366. 				if ( $Model -match $pattern ) {
  367. 					$Model = [System.Text.RegularExpressions.Regex]::Replace( $Model, $pattern, "" )
  368. 				}
  369. 				# Remove "/ Sailplane" of which the "plane" part will be garbled through the model text due to columns in PDF being too narrow
  370. 				if ( $Model.StartsWith( "/ Sail" ) ) {
  371. 					$newmodel = $Model.Substring( 6 )
  372. 					# Remove first lower case "p"
  373. 					$p = $newmodel.IndexOf( 'p', [System.StringComparison]::InvariantCulture )
  374. 					if ( $p -ne -1 ) {
  375. 						$newmodel = ( "{0}{1}" -f $newmodel.Substring( 0, $p ), $newmodel.Substring( $p + 1 ) )
  376. 						# Remove first lower case "l" following removed "p"
  377. 						$l = $newmodel.IndexOf( 'l', $p, [System.StringComparison]::InvariantCulture )
  378. 						if ( $l -ne -1 ) {
  379. 							$newmodel = ( "{0}{1}" -f $newmodel.Substring( 0, $l ), $newmodel.Substring( $l + 1 ) )
  380. 							# Remove first lower case "a" following removed "l"
  381. 							$a = $newmodel.IndexOf( 'a', $l, [System.StringComparison]::InvariantCulture )
  382. 							if ( $a -ne -1 ) {
  383. 								$newmodel = ( "{0}{1}" -f $newmodel.Substring( 0, $a ), $newmodel.Substring( $a + 1 ) )
  384. 								# Remove first lower case "n" following removed "a"
  385. 								$n = $newmodel.IndexOf( 'n', $a, [System.StringComparison]::InvariantCulture )
  386. 								if ( $n -ne -1 ) {
  387. 									$newmodel = ( "{0}{1}" -f $newmodel.Substring( 0, $n ), $newmodel.Substring( $n + 1 ) )
  388. 									# Remove first lower case "e" and trailing whitespace following removed "n"
  389. 									$e = $newmodel.IndexOf( 'e', $n, [System.StringComparison]::InvariantCulture )
  390. 									if ( $e -ne -1 ) {
  391. 										$newmodel = ( "{0}{1}" -f $newmodel.Substring( 0, $e ), $newmodel.Substring( $e + 1 ).Trim( ) )
  392. 										$Model = $newmodel
  393. 									}
  394. 								}
  395. 							}
  396. 						}
  397. 					}
  398. 				}
  399. 				$found = $true
  400. 				"{0}`t`t{1}" -f $Registration, $Model
  401. 			}
  402. 		}
  403. 	}
  404. 	if ( $Debug ) {
  405. 		Write-Host ( "Finished at {0} (elapsed time {1})`n`n" -f ( Get-Date ), $StopWatch.Elapsed )
  406. 		$StopWatch.Stop( )
  407. 	}
  408. } else {
  409. 	# No database text file found
  410. 	if ( $Quiet ) {
  411. 		if ( $Debug ) {
  412. 			Write-Host ( "Downloaded Lithuanian aircraft register database file `"{0}`" not found" -f $dbfile )
  413. 		}
  414. 		exit 1
  415. 	} else {
  416. 		$message = "No downloaded Lithuanian aircraft register database was found.`n`nDo you want to open the download webpage for the database now?"
  417. 		$title   = 'No Database Found'
  418. 		$buttons = 'YesNo'
  419. 		Add-Type -AssemblyName System.Windows.Forms
  420. 		$answer = [System.Windows.Forms.MessageBox]::Show( $message, $title, $buttons )
  421. 		if ( $answer -eq "Yes" ) {
  422. 			$url = 'https://tka.lt/oro-transportas/katalogas/register-of-civil-aircraft-of-the-republic-of-lithuania/?lang=en'
  423. 			Start-Process $url
  424. 		} else {
  425. 			ShowHelp( 'No downloaded Lithuanian aircraft register database found, please download it and try again' )
  426. 		}
  427. 	}
  428. }
  429.  

page last modified: 2024-04-16; loaded in 0.0150 seconds