topbanner_forum
  *

avatar image

Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
  • August 22, 2019, 05:13 PM
  • Proudly celebrating 13 years online.
  • Donate now to become a lifetime supporting member of the site and get a non-expiring license key for all of our programs.
  • donate

Author Topic: IDEA: Convert Radio Frequency scan Data for 3 Manufacturers Data structures  (Read 1088 times)

floydlloyd

  • Supporting Member
  • Joined in 2019
  • **
  • Posts: 4
    • View Profile
    • Donate to Member
Hi all,

I am an Audio Engineer at a Concert Hall and frequently use Wireless Microphone technology. I have to co-ordinate the Radio Frequency assignments to avoid interference.
There are 3 main Manufacturers of this gear, and they use different .csv file structures for the data imported into their equipment to generate usable non interfering frequency selections.
I've written a Power Shell script that takes the .csv output of a very common handheld Radio Frequency scanner and converts it to the proper structure for importation into the various Manufacturers equipment to ease the process of assigning Frequencies to Wireless Microphones.
I love it ... it works, but is clunky, and I'd like someone to make it robust and multi platform if possible. Currently to run it on Mac I load a Windows Virtual Machine and run it that way ... ugh
I do have a budget line for this so please let me know if it's too much for the "snacks" section .... if so, we can move it to an appropriate spot.

Cheers and thanks,

Lloyd B


ewemoa

  • Honorary Member
  • Joined in 2008
  • **
  • Posts: 2,897
    • View Profile
    • Donate to Member
Not sure how relevant it is, but Powershell Core is (somewhat?) multi-platform.  Perhaps it's possible that what you have is already (or close to being?) multi-platform?

floydlloyd

  • Supporting Member
  • Joined in 2019
  • **
  • Posts: 4
    • View Profile
    • Donate to Member
Hi Ewemoa,

I would really like to be able to release this to the Audio community as a gift to those who would find it useful. To that end  I'd want it to be as simple as ... "run this" if possible.

In it's current form, there is a niggling issue where a file selection dialog popup appears behind the main window and unless you know it's there, the thing appears to be locked up. I was unable to solve it in a reasonable amount of time and got frustrated.

From what I've read it could run on Mac with some tweaking  and effort on the end users part to install stuff on the Mac.

I don't have knowledge of any language, but seem to be able to at least intrinsically understand the concept of programming. It was very mentally taxing and time consuming for me to constantly refer to the Powershell documentation and find existing snippets to borrow. I'd also hate to be the person who wrote something so insecure that it could takeover the machine or some dumb thing like that.

That "hidden" dialog is a real pain, as others who have tested it for me have gotten stumped.

I suppose I could be happier if someone were to at least help solve that issue and maybe find a straightforward way to load the proper libraries and run it on a Mac as simply as possible.

I think the script itself is reasonably commented to give someone an Idea what I'm trying to do.

Thanks for the inspiration to explain things a little further.


ewemoa

  • Honorary Member
  • Joined in 2008
  • **
  • Posts: 2,897
    • View Profile
    • Donate to Member
Below are some possibly relevant thoughts, perhaps others will jump in with better suggestions / corrections.

If you're looking for something that doesn't involve additionally installing something and be multi-platform, I guess Powershell Core isn't going to do as that would also need to be installed.  Also, not everything written for the original Windows Powershell is going to run with Powershell Core -- this very much depends on the code in question though.

One general alternative path is a rewrite in something like Node.js (+ nexe), Nim, or something else which has the practical option of producing an executable for each platform you have an interest in deploying to.  Some of these options may result in a much larger download though -- unfortunately, it can often be the case that the ones that are easier to write the code for tend to produce larger files.

Depending on the details of what your code does, there may be another alternative that might work.  It's the idea of writing a web-based app (though it could be stored in local files, so you wouldn't need network access to run it) that runs in a web browser.

Without seeing and working with the code in question a bit though, it's not clear which alternative might be appropriate and how much work it might be to carry out.

Do you mind posting the code for others to examine?  Perhaps if the details can be studied, someone can give a better assessment about what might be involved.
« Last Edit: August 05, 2019, 09:16 PM by ewemoa »

Shades

  • Member
  • Joined in 2006
  • **
  • Posts: 2,569
    • View Profile
    • Donate to Member
Java has support for all operating systems. But might be overkill and an extra software dependency, which may be a problem for some.

There is software that is able to do such conversions. Quite some time ago I had to take look into the Bizztalk Server software from Microsoft to make the output of one piece of middleware to fit into another piece of middleware. While that was a fruitless endeavor (and way too expensive), the concept behind it might actually be helpful in the situation the OP describes.

The Bizztalk software allowed you to create adapters that take the output from one piece of software and "feed" that to an adapter for the other piece of software and have these pieces of software communicating directly. Those adapters could be made with a GUI and once created, they would function indefinitely. Bizztalk could do the same with files and lots of other types of data. Now, Bizztalk is a very expensive proposition, but there is an alternative called: FlowHeater Designer, which does use the concept of adapters and allows you to create them in a visual way. FlowHeater Designer is not nearly as extensive as BizzTalk is, but that is reflected in the price.

From what I understand is that content restructuring in a csv file is required. It would require 3 adapters to be created (one for each Manufacturer) and the FlowHeater software would be able to convert the content between these adapters, each generating a file: content_<manufacturer.name>.csv, ready to be imported into the software from each manufacturer. How to do that automatically within the Mac operating system is up to you. I make it a point to not work with any Apple gear, whenever I can think of a reason no to. 

You can try their freeware version to see if this type of software can actually help out. I have no affiliation with this software and no real experience with it either. But as a concept I do see possibilities.

floydlloyd

  • Supporting Member
  • Joined in 2019
  • **
  • Posts: 4
    • View Profile
    • Donate to Member
Thanks you two. I am away from my desk for the next couple days but will post the script and my description file, and a test .csv to be operated on as soon as I get back.


floydlloyd

  • Supporting Member
  • Joined in 2019
  • **
  • Posts: 4
    • View Profile
    • Donate to Member
Hi everyone,

Thanks for replying.

I've attached the script and some documentation with a folder of .csv files to use as test files. They were generated by the Handheld Spectrum analyzer and are representative of real data but there was very little radio activity so the actual variance in numbers is limited. Doesn't look like much when plotted on a graph but will be sufficient to test the script.

I also remembered that I'd like to add a "selectable on startup of script" function ... the ability to select a . csv and convert it between formats and appropriately name and save the output. csv file.

So it would be ... Script starts by asking "what do you want to do?"
1. Create. csv files from an RF Explorer scan
2. Convert .csv between existing manufacturer created scans

Industry folks have asked me for this feature as they generally use the manufacturers actual wireless Mic receiver to do the scans (not the handheld analyzer that generated these test files) and the machine outputs a. csv in that manufacturers corresponding format.

I suppose I could revisit my powershell skills LOL and add this function in, but have been very busy at the Concert Hall and haven't had much time to get it done.

Hope that makes sense and that someone will take this on :-)

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,221
    • View Profile
    • Donate to Member
There's now the Avalonia Project which provides a cross-platform UI solution for PowerShell (using XAML), (Windows, Linux, OSX), currently in beta but it shouldn't be hard to add a simple GUI to the script.
« Last Edit: August 07, 2019, 12:50 PM by 4wd »

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,221
    • View Profile
    • Donate to Member
In it's current form, there is a niggling issue where a file selection dialog popup appears behind the main window and unless you know it's there, the thing appears to be locked up. I was unable to solve it in a reasonable amount of time and got frustrated.

From here System.Windows.Forms.OpenFileDialog always ontop - add a check for how the script was run and set $ShowHelp appropriately:

Code: PowerShell [Select]
  1. function Read-OpenFileDialog([string]$WindowTitle, [string]$InitialDirectory, [string]$Filter = "All files (*.*)|*.*", [switch]$AllowMultiSelect)
  2. {
  3.     Add-Type -AssemblyName System.Windows.Forms
  4.     $openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
  5.     $ShowHelp = $false
  6. # See https://community.idera.com/database-tools/powershell/ask_the_experts/f/learn_powershell_from_don_jones-24/13493/system-windows-forms-openfiledialog-always-ontop
  7.     if ($Host.name -eq "ConsoleHost") {$ShowHelp = $true}
  8.     $openFileDialog.Title = $WindowTitle
  9.     if (![string]::IsNullOrWhiteSpace($InitialDirectory)) { $openFileDialog.InitialDirectory = $InitialDirectory }
  10.     $openFileDialog.Filter = $Filter
  11.     if ($AllowMultiSelect) { $openFileDialog.MultiSelect = $true }
  12.     $openFileDialog.ShowHelp = $ShowHelp    # Without this line the ShowDialog() function may hang depending on system configuration and running from console vs. ISE.
  13.     $openFileDialog.ShowDialog() > $null
  14.     if ($AllowMultiSelect) { return $openFileDialog.Filenames } else { return $openFileDialog.Filename }
  15. }

ewemoa

  • Honorary Member
  • Joined in 2008
  • **
  • Posts: 2,897
    • View Profile
    • Donate to Member
Below are some observations and notes.

I tried the script out on a Windows 10 Pro box, but didn't notice dialog boxes being behind things.  Script execution was tested both from Windows Explorer as well as from a Powershell window.  It might be helpful to be able to replicate the issue -- perhaps it's for particular versions of Windows?

For running a test, one of the files from the TestFilesFromRFexplorer directory was selected.  It appears that all files in that directory get wiped by the end of the script.  I wonder if that is desirable behavior.  Also noticed some error output, but I did find a .zip file that appeared to contain the original file along with 2 converted ones.

Regarding running on macos, I looked a bit into 4wd's Avalonia idea, and came across: https://github.com/i...nsoftware/psavalonia "Avalonia bindings for PowerShell".  The supported versions of Powershell there look like Powershell Core though, so I tried running the script via Powershell Core.  The result was a fair number of error messages so I stopped its execution.

I also tried creating a simple python script to open a file dialog and tried packaging and running this on Windows and macos using PyInstaller.  Interestingly enough, there was no problem with the dialog being behind things on Windows, but on macos there was.  It appears to be something that other folks have encountered and although I found multiple work-arounds, none of them worked for my particular environment (though apparently some of them do work for other folks).  (On a side note, my experience with macos (OS X, etc.) over the years has been that backward compatibility of certain types of things is not particularly a high priority, with adjustments sometimes being necessary when there are new OS releases, so even if something were found to work, it might be good to keep in mind that future OS releases might necessitate updates.  Perhaps it's misleading to single out Apple in this regard.)

Regarding "Convert .csv between existing manufacturer created scans", perhaps if this general conversion portion were implemented, the current script might benefit from being based on it.  If someone were to start on this though, may be it would be better to consider Powershell Core or something else more multi-platform friendly, rather than Windows Powershell.

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,221
    • View Profile
    • Donate to Member
I tried the script out on a Windows 10 Pro box, but didn't notice dialog boxes being behind things.  Script execution was tested both from Windows Explorer as well as from a Powershell window.  It might be helpful to be able to replicate the issue -- perhaps it's for particular versions of Windows?

Interestingly, I always had one of its dialogs open behind other windows, (either the OpenFile or the final Retry/Cancel), until I added the above run check.

The Retry/Cancel dialog still opens behind other windows sometimes.

The other problem, which I believe is related to the use of the Show-Command cmdlet, is that selecting Cancel still opens the OpenFile dialog.

Regarding running on macos, I looked a bit into 4wd's Avalonia idea, and came across: https://github.com/i...nsoftware/psavalonia "Avalonia bindings for PowerShell".  The supported versions of Powershell there look like Powershell Core though, so I tried running the script via Powershell Core.  The result was a fair number of error messages so I stopped its execution.

Due to the use of Show-Command, it tries to create a Window using WPF, (by the looks), and fails under PowerShell Core, (doesn't exist) - you get the errors in PoShCore regardless of whether Avalonia is installed or not.

Regarding "Convert .csv between existing manufacturer created scans", perhaps if this general conversion portion were implemented, the current script might benefit from being based on it.

This would be a better idea, I might get a chance to look at it later and try and isolate the relevant routines, (still overseas on a low-powered laptop atm).
« Last Edit: August 12, 2019, 05:35 AM by 4wd »

ewemoa

  • Honorary Member
  • Joined in 2008
  • **
  • Posts: 2,897
    • View Profile
    • Donate to Member
Interestingly, I always had one of its dialogs open behind other windows, (either the OpenFile or the final Retry/Cancel), until I added the above run check.

The Retry/Cancel dialog still opens behind other windows sometimes.

At least one of us can reproduce at least some of the time :)

The other problem, which I believe is related to the use of the Show-Command cmdlet, is that selecting Cancel still opens the OpenFile dialog.

Ah, I hadn't noticed this.

I might get a chance to look at it later and try and isolate the relevant routines, (still overseas on a low-powered laptop atm).

Do you think a Powershell Core implementation would make sense?

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,221
    • View Profile
    • Donate to Member
Do you think a Powershell Core implementation would make sense?


Yes, definitely ... but since I've only used Windows PowerShell up til now ...

2019-08-14 10_13_42.pngIDEA: Convert Radio Frequency scan Data for 3 Manufacturers Data structures

2019-08-14 10_17_17.pngIDEA: Convert Radio Frequency scan Data for 3 Manufacturers Data structures

The below is functionally similar to the original PoSh script, the changes are:
  • Put almost everything into Functions so they can be transplanted into other scripts.
  • Added a WPF GUI (the implemented version is just something simple but more than doubles the size of the script) - it would benefit from having a ListBox that shows the selected files and a TextBox that shows the progress of the operation.  I kept it simple so as to not invest too much time into something that might be replaced with either, for example, an Avalonia based interface or some other language/GUI, (eg. Python).
  • Added the ability to convert between RF Explorer, Sennheiser, and Shure input CSVs.  For example, select a Sennheiser file, select the Shure output option, hit Start.
  • Options to either delete the original files and create a distribution archive.

NOTE: In my limited testing it worked fine but there are most likely bugs and there is no error checking, (the original script didn't have any either).

Tested on: Windows 10 Pro x64, PowerShell 5.1.18362.145, .NET 4.8

Broken down into sections, you have:
  • Global variables - there are three, two of them are defined later in the script by prefacing with $global:
  • Functions - file request and working directory creation, conversions, archive creation
  • GUI - everything else plus what happens when you click the buttons

RFExplorer.ps1
Code: PowerShell [Select]
  1. <# This form was created using POSHGUI.com  a free online gui designer for PowerShell
  2. .NAME
  3.     .\RFExplorer.ps1
  4. #>
  5.  
  6. # Global variables
  7. $initMessage = 'This script lets you browse to and select the pertinent .csv spectrum scan files that were output by your RF Explorer device, sort them by creation time, join them together and output 2 seperate files plus the original un-modified scan files into a newly created subdirectory named with the current date and time.
  8.  
  9. 1. SHURE-importable
  10.         Shure Wireless workbench accepts .csv files consisting of
  11.         2 columns (no Headers) -> Frequency in MHz,Level in DBm
  12.         (columns seperated by a comma)
  13.                 492.6,-103
  14.                 492.625,-96
  15.                 492.65,-102
  16. 2. SENNHEISER-Importable
  17.         Sennheiser Wireless Systems Manager is more complicated. They expect a descriptive 2 column header then 3 columns of data -> Frequency in KHz;;Level in DB (columns seperated by a semi-colon)
  18.  
  19.                 Receiver;01
  20.                 Date/Time;$lastwrittentime
  21.                 RFUnit;dB
  22.                 Owner;$FirstName $LastName
  23.                 ScanCity;$ScanCity
  24.                 ScanComment;
  25.                 ScanCountry;$ScanCountry
  26.                 ScanDescription;$ScanDescription
  27.                 ScanInteriorExterior;$ScanInteriorORExterior
  28.                 ScanLatitude;
  29.                 ScanLongitude;
  30.                 ScanName;$ScanName
  31.                 ScanPostalCode;$ScanPostalCode
  32.  
  33.                 Frequency Range [kHz];$FreqRangeL;$FreqRangeH;$FreqSpan
  34.                 Frequency;RF level (%);RF level
  35.                 492600;;4
  36.                 492625;;11
  37.                 492650;;5
  38.  
  39. The $variables in the Sennheiser header get pulled from the info you enter into an initial popup dialog so you can archive AND/OR upload a zip file of the original RF Explorer scan chunks along with the 2 formatted files and a descriptive text file to an online database of venue scans from around the world    http://www.bestaudio.com/spectrum-scans/
  40. I am using Nuts AboutNets Touchstone Pro Software $49US   http://nutsaboutnets.com/touchstone/    to interact with the RF Explorer for setting scan parameters and actually running the scans. The native software that comes with RF explorer can do everything but I found it time consuming to break the spectrum down into smaller chunks to increase resolution'
  41.  
  42. Function Get-Files {
  43.   # Show an Open File Dialog and return the files selected by the user.
  44.   $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{
  45.     InitialDirectory = $scanDirectory
  46. #    InitialDirectory = [Environment]::GetFolderPath('MyDocuments')
  47.     Filter = 'RF Explorer Files|*.csv|All Files|*.*'
  48.     MultiSelect = $true
  49.   }
  50.  
  51.   $null = $FileBrowser.ShowDialog()
  52.  
  53.   if ($FileBrowser.FileNames.Count -eq 0) {
  54.     return
  55.   } else {
  56.     $RFexplorerDataDirectory = Split-Path $FileBrowser.FileNames[0] -Parent
  57.     $global:lastwrittentime = (Get-ItemProperty -Path $FileBrowser.FileNames[0]).LastWriteTime.tostring("MM-MMMM-dd-yyyy-hh-mm-ss")
  58.   }
  59.  
  60.   $currentdatetime = Get-Date -f ("MM-MMMM-dd-yyyy-hh-mm-ss")
  61.   $destDir = "$($RFexplorerDataDirectory)\$($currentdatetime)"
  62.   New-Item -ItemType Directory "$($destDir)" | Out-Null
  63.  
  64.   # Copy/Move selected files to Destination directory
  65.   for ($i = 0; $i -lt $FileBrowser.FileNames.Count; $i++) {
  66.   # Clear out non-CSV files from destination directory
  67.     if ($CheckBox1.CheckState) {
  68.       Move-Item $FileBrowser.FileNames[$i] -dest "$destDir"
  69.     } else {
  70.       Copy-Item $FileBrowser.FileNames[$i] -dest "$destDir"
  71.     }
  72.   }
  73.   return $destDir
  74. }
  75.  
  76. Function Senn-RFE {
  77.   param (
  78.     [double]$n1,
  79.     [double]$n2
  80.   )
  81.   if ($n1 -gt 1000) {
  82.     $n1 /= 1000
  83.     $n2 -= 107
  84.   }
  85.   return "$($n1);$($n2)"
  86. }
  87.  
  88. Function ConvertTo-RFE {
  89.   param (
  90.     [string]$file
  91.   )
  92.   Get-Content $file | `
  93.     Where-Object {$_ -match '^\d+.+'} | `
  94.     Foreach-Object {$_ -replace ";;" , ";"} | `
  95.     Foreach-Object {$_ -replace "," , ";"} | `
  96.     ForEach-Object {$fields = $_.Split(";") ;
  97.       Out-File -FilePath "intermediate.tmp" -InputObject (Senn-RFE $fields[0] $fields[1]) -Append -Encoding utf8}
  98. }
  99.  
  100. Function ConvertTo-Shure {
  101.   param (
  102.     [string]$file
  103.   )
  104.   (Get-Content $file) | `
  105.     Foreach-Object {$_ -replace " -" , "-"} | `
  106.     Foreach-Object {$_ -replace ";" , ","} | `
  107.     Set-Content -Path "SHURE-Importable-$($lastwrittentime).csv"
  108. }
  109.  
  110.  
  111. Function ConvertTo-Sennheiser {
  112.   param (
  113.     [string]$file
  114.   )
  115.   # Create a new array to temporarily house the dBm to dB conversion data that comes later
  116.   $BeingModified = New-Object System.Collections.ArrayList
  117.  
  118.   (Get-Content $file) | `
  119. #    Foreach-Object {$_ -replace "(\d{3})\.(\d{2})" , '$1$2'} |
  120. #    Foreach-Object {$_ -replace "(-\d{3})(\d{2})" , '$1.$2'} |
  121.     Foreach-Object {$_ -replace ";" , ";;"} | `
  122.     Foreach-Object {$_ -replace "," , ";;"} | `
  123. # Change the RF Level data from dBm to Sennheisers' dB by adding 107
  124.     Foreach-Object {$_
  125.       $fields = $_.Split(";")
  126.       $freq = [double]$fields[0]*1000
  127.       #$blank = $fields[1]
  128.       $dBm = [double]$fields[2]
  129.       [double]$dB = $dBm + 107
  130.       # Create array with the new values to use later to replace things in the new output file
  131.       [void]$BeingModified.Add("$freq;;$dB")
  132.     }
  133.  
  134.   $BeingModified | Set-Content $file
  135.   $wwbbasefile = "$($destDirectory)\$($file)"
  136.  
  137.   # Get FreqRange and Span Data into variables
  138.  
  139.   $FreqRangeL = Get-Content $wwbbasefile | Select -First 1
  140.   $FreqRangeH = Get-Content $wwbbasefile | Select -Last 1
  141.   $FreqRange_ = Get-Content $wwbbasefile | Select -Last 2
  142.  
  143.   # parse the CSV data back into separate variables, one for each column
  144.  
  145.   $dataArrayL = $FreqRangeL.Split(";")
  146.   $FreqRangeL = $dataArrayL[0]
  147.  
  148.   $dataArrayH = $FreqRangeH.Split(";")
  149.   $FreqRangeH = $dataArrayH[0]
  150.  
  151.   $dataArray_ = $FreqRange_.Split(";")
  152.   $FreqRange_ = $dataArray_[0]
  153.  
  154.   # Calculate the frequency span
  155.   $FreqSpan = $FreqRangeH - $FreqRange_
  156.  
  157.   # Define the Header required for Sennheiser Wireless Systems Manager to be able to read the .csv file
  158.  
  159.   $sennheader=
  160. @"
  161. Receiver;01
  162. Date/Time;$lastwrittentime
  163. RFUnit;dB
  164. Owner;$($TextBox1.Text) $($TextBox2.Text)
  165. ScanCity;$($TextBox3.Text)
  166. ScanComment;
  167. ScanCountry;$($ComboBox1.Text)
  168. ScanDescription;$($TextBox4.Text)
  169. ScanInteriorExterior;$($ComboBox2.Text)
  170. ScanLatitude;
  171. ScanLongitude;
  172. ScanName;$($TextBox5.Text)
  173. ScanPostalCode;$($TextBox6.Text)
  174. Frequency Range [kHz];$FreqRangeL;$FreqRangeH;$FreqSpan
  175. Frequency;RF level (%);RF level
  176. "@
  177.  
  178.  
  179.   # Insert the header text into  a text file
  180.   $sennheader | Set-Content sennheader.txt
  181.  
  182.   # Join the header file and .csv data into final output file
  183.   Get-Content sennheader.txt, $wwbbasefile | Set-Content "SENNHEISER-Importable-$($lastwrittentime).csv"
  184. }
  185.  
  186. Function Create-Distribution {
  187.   # Create a directory to store the zipped results for upload to Pet Erskines database
  188.   New-Item -ItemType Directory "$destDirectory\For Distribution" | Out-Null
  189.   $zipName = "$($destDirectory)\For Distribution\$($TextBox3.Text)-$($TextBox7.Text)-$($ComboBox1.Text)-$($TextBox8.Text)-$($lastwrittentime)-$($TextBox1.Text)-$($TextBox2.Text).zip"
  190.   Compress-Archive -Path "$($destDirectory)\*.csv" -DestinationPath "$($zipName)"
  191. }
  192.  
  193. Add-Type -AssemblyName Microsoft.VisualBasic
  194. Add-Type -AssemblyName System.Windows.Forms
  195. [System.Windows.Forms.Application]::EnableVisualStyles()
  196.  
  197. $Form                            = New-Object system.Windows.Forms.Form
  198. $Form.ClientSize                 = '400,500'
  199. $Form.text                       = "RFTSSE"
  200. $Form.TopMost                    = $false
  201.  
  202. $Label1                          = New-Object system.Windows.Forms.Label
  203. $Label1.text                     = "First Name:"
  204. $Label1.AutoSize                 = $true
  205. $Label1.width                    = 25
  206. $Label1.height                   = 10
  207. $Label1.location                 = New-Object System.Drawing.Point(25,20)
  208. $Label1.Font                     = 'Microsoft Sans Serif,10'
  209.  
  210. $TextBox1                        = New-Object system.Windows.Forms.TextBox
  211. $TextBox1.multiline              = $false
  212. $TextBox1.width                  = 210
  213. $TextBox1.height                 = 20
  214. $TextBox1.location               = New-Object System.Drawing.Point(160,18)
  215. $TextBox1.Font                   = 'Microsoft Sans Serif,10'
  216.  
  217. $Label2                          = New-Object system.Windows.Forms.Label
  218. $Label2.text                     = "Last Name:"
  219. $Label2.AutoSize                 = $true
  220. $Label2.width                    = 25
  221. $Label2.height                   = 10
  222. $Label2.location                 = New-Object System.Drawing.Point(25,46)
  223. $Label2.Font                     = 'Microsoft Sans Serif,10'
  224.  
  225. $TextBox2                        = New-Object system.Windows.Forms.TextBox
  226. $TextBox2.multiline              = $false
  227. $TextBox2.width                  = 210
  228. $TextBox2.height                 = 20
  229. $TextBox2.location               = New-Object System.Drawing.Point(160,43)
  230. $TextBox2.Font                   = 'Microsoft Sans Serif,10'
  231.  
  232. $Label3                          = New-Object system.Windows.Forms.Label
  233. $Label3.text                     = "Scan City:"
  234. $Label3.AutoSize                 = $true
  235. $Label3.width                    = 25
  236. $Label3.height                   = 10
  237. $Label3.location                 = New-Object System.Drawing.Point(25,70)
  238. $Label3.Font                     = 'Microsoft Sans Serif,10'
  239.  
  240. $TextBox3                        = New-Object system.Windows.Forms.TextBox
  241. $TextBox3.multiline              = $false
  242. $TextBox3.width                  = 210
  243. $TextBox3.height                 = 20
  244. $TextBox3.location               = New-Object System.Drawing.Point(160,68)
  245. $TextBox3.Font                   = 'Microsoft Sans Serif,10'
  246.  
  247. $Label4                          = New-Object system.Windows.Forms.Label
  248. $Label4.text                     = "Scan Country:"
  249. $Label4.AutoSize                 = $true
  250. $Label4.width                    = 25
  251. $Label4.height                   = 10
  252. $Label4.location                 = New-Object System.Drawing.Point(25,95)
  253. $Label4.Font                     = 'Microsoft Sans Serif,10'
  254.  
  255. $ComboBox1                       = New-Object system.Windows.Forms.ComboBox
  256. $ComboBox1.width                 = 210
  257. $ComboBox1.height                = 20
  258. @("Afghanistan","Albania","Algeria","American Samoa","Andorra","Angola","Anguilla","Antarctica","Antigua and Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia and Herzegovina","Botswana","Bouvet Island","Brazil","British Antarctic Territory","British Indian Ocean Territory","British Virgin Islands","Brunei","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Canada","Canton and Enderbury Islands","Cape Verde","Cayman Islands","Central African Republic","Chad","Chile","China","Christmas Island","Cocos [Keeling] Islands","Colombia","Comoros","Congo - Brazzaville","Congo - Kinshasa","Cook Islands","Costa Rica","Croatia","Cuba","Cyprus","Czech Republic","Côte d’Ivoire","Denmark","Djibouti","Dominica","Dominican Republic","Dronning Maud Land","East Germany","Ecuador","Egypt","El Salvador","Equatorial Guinea","Eritrea","Estonia","Ethiopia","Falkland Islands","Faroe Islands","Fiji","Finland","France","French Guiana","French Polynesia","French Southern Territories","French Southern and Antarctic Territories","Gabon","Gambia","Georgia","Germany","Ghana","Gibraltar","Greece","Greenland","Grenada","Guadeloupe","Guam","Guatemala","Guernsey","Guinea","Guinea-Bissau","Guyana","Haiti","Heard Island and McDonald Islands","Honduras","Hong Kong SAR China","Hungary","Iceland","India","Indonesia","Iran","Iraq","Ireland","Isle of Man","Israel","Italy","Jamaica","Japan","Jersey","Johnston Island","Jordan","Kazakhstan","Kenya","Kiribati","Kuwait","Kyrgyzstan","Laos","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macau SAR China","Macedonia","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Marshall Islands","Martinique","Mauritania","Mauritius","Mayotte","Metropolitan France","Mexico","Micronesia","Midway Islands","Moldova","Monaco","Mongolia","Montenegro","Montserrat","Morocco","Mozambique","Myanmar [Burma]","Namibia","Nauru","Nepal","Netherlands","Netherlands Antilles","Neutral Zone","New Caledonia","New Zealand","Nicaragua","Niger","Nigeria","Niue","Norfolk Island","North Korea","North Vietnam","Northern Mariana Islands","Norway","Oman","Pacific Islands Trust Territory","Pakistan","Palau","Palestinian Territories","Panama","Panama Canal Zone","Papua New Guinea","Paraguay","People's Democratic Republic of Yemen","Peru","Philippines","Pitcairn Islands","Poland","Portugal","Puerto Rico","Qatar","Romania","Russia","Rwanda","Réunion","Saint Barthélemy","Saint Helena","Saint Kitts and Nevis","Saint Lucia","Saint Martin","Saint Pierre and Miquelon","Saint Vincent and the Grenadines","Samoa","San Marino","Saudi Arabia","Senegal","Serbia","Serbia and Montenegro","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","Solomon Islands","Somalia","South Africa","South Georgia and the South Sandwich Islands","South Korea","Spain","Sri Lanka","Sudan","Suriname","Svalbard and Jan Mayen","Swaziland","Sweden","Switzerland","Syria","São Tomé and Príncipe","Taiwan","Tajikistan","Tanzania","Thailand","Timor-Leste","Togo","Tokelau","Tonga","Trinidad and Tobago","Tunisia","Turkey","Turkmenistan","Turks and Caicos Islands","Tuvalu","U.S. Minor Outlying Islands","U.S. Miscellaneous Pacific Islands","U.S. Virgin Islands","Uganda","Ukraine","Union of Soviet Socialist Republics","United Arab Emirates","United Kingdom","United States","Unknown or Invalid Region","Uruguay","Uzbekistan","Vanuatu","Vatican City","Venezuela","Vietnam","Wake Island","Wallis and Futuna","Western Sahara","Yemen","Zambia","Zimbabwe","Åland Islands") | ForEach-Object {[void] $ComboBox1.Items.Add($_)}
  259. $ComboBox1.location              = New-Object System.Drawing.Point(160,93)
  260. $ComboBox1.Font                  = 'Microsoft Sans Serif,10'
  261.  
  262. $Label5                          = New-Object system.Windows.Forms.Label
  263. $Label5.text                     = "Scan Description:"
  264. $Label5.AutoSize                 = $true
  265. $Label5.width                    = 25
  266. $Label5.height                   = 10
  267. $Label5.location                 = New-Object System.Drawing.Point(25,121)
  268. $Label5.Font                     = 'Microsoft Sans Serif,10'
  269.  
  270. $TextBox4                        = New-Object system.Windows.Forms.TextBox
  271. $TextBox4.multiline              = $false
  272. $TextBox4.width                  = 210
  273. $TextBox4.height                 = 20
  274. $TextBox4.location               = New-Object System.Drawing.Point(160,119)
  275. $TextBox4.Font                   = 'Microsoft Sans Serif,10'
  276.  
  277. $Label6                          = New-Object system.Windows.Forms.Label
  278. $Label6.text                     = "Scan Int or Ext:"
  279. $Label6.AutoSize                 = $true
  280. $Label6.width                    = 25
  281. $Label6.height                   = 10
  282. $Label6.location                 = New-Object System.Drawing.Point(25,146)
  283. $Label6.Font                     = 'Microsoft Sans Serif,10'
  284.  
  285. $ComboBox2                       = New-Object system.Windows.Forms.ComboBox
  286. $ComboBox2.width                 = 210
  287. $ComboBox2.height                = 20
  288. @('Interior','Exterior') | ForEach-Object {[void] $ComboBox2.Items.Add($_)}
  289. $ComboBox2.location              = New-Object System.Drawing.Point(160,144)
  290. $ComboBox2.Font                  = 'Microsoft Sans Serif,10'
  291.  
  292. $Label7                          = New-Object system.Windows.Forms.Label
  293. $Label7.text                     = "Scan Name:"
  294. $Label7.AutoSize                 = $true
  295. $Label7.width                    = 25
  296. $Label7.height                   = 10
  297. $Label7.location                 = New-Object System.Drawing.Point(25,172)
  298. $Label7.Font                     = 'Microsoft Sans Serif,10'
  299.  
  300. $TextBox5                        = New-Object system.Windows.Forms.TextBox
  301. $TextBox5.multiline              = $false
  302. $TextBox5.width                  = 210
  303. $TextBox5.height                 = 20
  304. $TextBox5.location               = New-Object System.Drawing.Point(160,170)
  305. $TextBox5.Font                   = 'Microsoft Sans Serif,10'
  306.  
  307. $Label8                          = New-Object system.Windows.Forms.Label
  308. $Label8.text                     = "Scan Postcode:"
  309. $Label8.AutoSize                 = $true
  310. $Label8.width                    = 25
  311. $Label8.height                   = 10
  312. $Label8.location                 = New-Object System.Drawing.Point(25,197)
  313. $Label8.Font                     = 'Microsoft Sans Serif,10'
  314.  
  315. $TextBox6                        = New-Object system.Windows.Forms.TextBox
  316. $TextBox6.multiline              = $false
  317. $TextBox6.width                  = 210
  318. $TextBox6.height                 = 20
  319. $TextBox6.location               = New-Object System.Drawing.Point(160,195)
  320. $TextBox6.Font                   = 'Microsoft Sans Serif,10'
  321.  
  322. $Label9                          = New-Object system.Windows.Forms.Label
  323. $Label9.text                     = "Scan State/Province:"
  324. $Label9.AutoSize                 = $true
  325. $Label9.width                    = 25
  326. $Label9.height                   = 10
  327. $Label9.location                 = New-Object System.Drawing.Point(25,222)
  328. $Label9.Font                     = 'Microsoft Sans Serif,10'
  329.  
  330. $TextBox7                        = New-Object system.Windows.Forms.TextBox
  331. $TextBox7.multiline              = $false
  332. $TextBox7.width                  = 210
  333. $TextBox7.height                 = 20
  334. $TextBox7.location               = New-Object System.Drawing.Point(160,220)
  335. $TextBox7.Font                   = 'Microsoft Sans Serif,10'
  336.  
  337. $Label10                         = New-Object system.Windows.Forms.Label
  338. $Label10.text                    = "Scan Venue:"
  339. $Label10.AutoSize                = $true
  340. $Label10.width                   = 25
  341. $Label10.height                  = 10
  342. $Label10.location                = New-Object System.Drawing.Point(25,247)
  343. $Label10.Font                    = 'Microsoft Sans Serif,10'
  344.  
  345. $TextBox8                        = New-Object system.Windows.Forms.TextBox
  346. $TextBox8.multiline              = $false
  347. $TextBox8.width                  = 210
  348. $TextBox8.height                 = 20
  349. $TextBox8.location               = New-Object System.Drawing.Point(160,245)
  350. $TextBox8.Font                   = 'Microsoft Sans Serif,10'
  351.  
  352. $Button1                         = New-Object system.Windows.Forms.Button
  353. $Button1.text                    = "Select files ..."
  354. $Button1.width                   = 300
  355. $Button1.height                  = 30
  356. $Button1.location                = New-Object System.Drawing.Point(50,280)
  357. $Button1.Font                    = 'Microsoft Sans Serif,10'
  358.  
  359. $Button2                         = New-Object system.Windows.Forms.Button
  360. $Button2.text                    = "Start"
  361. $Button2.width                   = 95
  362. $Button2.height                  = 30
  363. $Button2.location                = New-Object System.Drawing.Point(50,320)
  364. $Button2.Font                    = 'Microsoft Sans Serif,10'
  365.  
  366. $Label11                         = New-Object system.Windows.Forms.Label
  367. $Label11.text                    = "Output"
  368. $Label11.AutoSize                = $true
  369. $Label11.width                   = 25
  370. $Label11.height                  = 10
  371. $Label11.location                = New-Object System.Drawing.Point(228,330)
  372. $Label11.Font                    = 'Microsoft Sans Serif,10'
  373.  
  374. $RadioButton1                    = New-Object system.Windows.Forms.RadioButton
  375. $RadioButton1.text               = "Sennheiser"
  376. $RadioButton1.AutoSize           = $true
  377. $RadioButton1.width              = 104
  378. $RadioButton1.height             = 20
  379. $RadioButton1.location           = New-Object System.Drawing.Point(213,350)
  380. $RadioButton1.Font               = 'Microsoft Sans Serif,10'
  381.  
  382. $RadioButton2                    = New-Object system.Windows.Forms.RadioButton
  383. $RadioButton2.text               = "Shure"
  384. $RadioButton2.AutoSize           = $true
  385. $RadioButton2.width              = 104
  386. $RadioButton2.height             = 20
  387. $RadioButton2.location           = New-Object System.Drawing.Point(213,370)
  388. $RadioButton2.Font               = 'Microsoft Sans Serif,10'
  389.  
  390. $RadioButton3                    = New-Object system.Windows.Forms.RadioButton
  391. $RadioButton3.text               = "RF Explorer"
  392. $RadioButton3.AutoSize           = $true
  393. $RadioButton3.width              = 104
  394. $RadioButton3.height             = 20
  395. $RadioButton3.location           = New-Object System.Drawing.Point(213,390)
  396. $RadioButton3.Font               = 'Microsoft Sans Serif,10'
  397.  
  398. $RadioButton4                    = New-Object system.Windows.Forms.RadioButton
  399. $RadioButton4.text               = "Combined"
  400. $RadioButton4.AutoSize           = $true
  401. $RadioButton4.width              = 104
  402. $RadioButton4.height             = 20
  403. $RadioButton4.Checked            = $true
  404. $RadioButton4.location           = New-Object System.Drawing.Point(213,410)
  405. $RadioButton4.Font               = 'Microsoft Sans Serif,10'
  406.  
  407. $CheckBox1                       = New-Object system.Windows.Forms.CheckBox
  408. $CheckBox1.text                  = "Delete originals"
  409. $CheckBox1.AutoSize              = $false
  410. $CheckBox1.width                 = 120
  411. $CheckBox1.height                = 20
  412. $CheckBox1.location              = New-Object System.Drawing.Point(50,370)
  413. $CheckBox1.Font                  = 'Microsoft Sans Serif,10'
  414.  
  415. $CheckBox2                       = New-Object system.Windows.Forms.CheckBox
  416. $CheckBox2.text                  = "Create archive"
  417. $CheckBox2.AutoSize              = $false
  418. $CheckBox2.width                 = 120
  419. $CheckBox2.height                = 20
  420. $CheckBox2.Checked               = $true
  421. $CheckBox2.location              = New-Object System.Drawing.Point(50,390)
  422. $CheckBox2.Font                  = 'Microsoft Sans Serif,10'
  423.  
  424. $Button3                         = New-Object system.Windows.Forms.Button
  425. $Button3.text                    = "Information"
  426. $Button3.width                   = 100
  427. $Button3.height                  = 30
  428. $Button3.location                = New-Object System.Drawing.Point(150,440)
  429. $Button3.Font                    = 'Microsoft Sans Serif,10'
  430.  
  431. $Form.controls.AddRange(@($Label1,$Label2,$Label3,$Label4,$Label5,$Label6,$Label7,$Label8,$Label9,$Label10,$Label11,$TextBox1,$TextBox2,$TextBox3,$TextBox4,$TextBox5,$TextBox6,$TextBox7,$TextBox8,$ComboBox1,$ComboBox2,$Button1,$Button2,$Button3,$RadioButton1,$RadioButton2,$RadioButton3,$RadioButton4,$CheckBox1,$CheckBox2))
  432.  
  433. # Select Files Button
  434. $Button1.Add_Click({
  435.   # Get the directory the working files are in
  436.   $global:destDirectory = Get-Files
  437.  
  438.   # Destination directory becomes working directory, so Push it
  439.   Push-Location -Path "$destDirectory"
  440.  
  441.   # Sort RF Explorer created .csv files by date and time, concat them into a temporary file
  442.   Get-ChildItem *.csv | sort LastWriteTime | % {$(Get-Content $_)} | Set-Content joined.tmp
  443. })
  444.  
  445. # Start Button
  446. $Button2.Add_Click({
  447.   if ($RadioButton1.Checked) {
  448.     ConvertTo-RFE joined.tmp
  449.     ConvertTo-Sennheiser intermediate.tmp
  450.   }
  451.   if ($RadioButton2.Checked) {
  452.     ConvertTo-RFE joined.tmp
  453.     ConvertTo-Shure intermediate.tmp
  454.   }
  455.   if ($RadioButton3.Checked) {
  456.     ConvertTo-RFE joined.tmp
  457.   }
  458.   if ($RadioButton4.Checked) {
  459.     ConvertTo-Shure joined.tmp
  460.     ConvertTo-Sennheiser joined.tmp
  461.   }
  462.  
  463.   # Remove non-CSV files
  464.   Remove-Item -Path "$($destDirectory)\*" -Exclude *.csv
  465.  
  466.   # Create archive for distribution
  467.   if ($CheckBox2.CheckState) {
  468.     Create-Distribution
  469.   }
  470.  
  471.   Pop-Location
  472. })
  473.  
  474. # Information Button
  475. $Button3.Add_Click({
  476.   $result = [Microsoft.VisualBasic.Interaction]::MsgBox($initMessage, 'OKOnly,SystemModal,Information', 'RFTSSE')
  477. })
  478.  
  479. [void]$Form.ShowDialog()
« Last Edit: August 14, 2019, 05:16 AM by 4wd »

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,221
    • View Profile
    • Donate to Member
Four problems became apparent in PowerShell Core (Windows) for the above code:
  • Initial window size could not be set
  • The font used was not recognised
  • The FileBrowser did not work (locked up the console)
  • The Information window relies on VB routines

It ran and opened a GUI but you couldn't do anything.

I've installed PowerShell Core under Windows Subsytem for Linux (WSL) so I can have a play, (also installed on a RasPi I've got with me) - doesn't run at all under PoShCore (Linux), to be expected.

ewemoa

  • Honorary Member
  • Joined in 2008
  • **
  • Posts: 2,897
    • View Profile
    • Donate to Member
I like the single UI approach.  Have been thinking whether the ability to load / save the fields at the top might make sense.  That might also make the functionality more easily packaged as a command line script for use with other tools.

Nice work with the new features and modularization.  The latter should make it easier to study and perhaps it will also facilitate work on Powershell Core compatibility. 

I guess one aspect to consider for multi-platform compatibility is file paths.  Possibly also line endings?  May be Avalonia or Powershell Core has paid some attention to these (and other) issues...

Hope to test it soon.

4wd

  • Supporting Member
  • Joined in 2006
  • **
  • Posts: 5,221
    • View Profile
    • Donate to Member
Could avoid the GUI altogether and revert to a series of Read-Host prompt/answer inputs plus include the ability to run as a standard command if all parameters are fulfilled on the command line.

Would be the quickest way to make it portable.

W.r.t. filepaths, PowerShell (Core) is pretty agnostic when it comes to using / or \ - either will do, plus it sees multiple occurrences, (eg. ////), as just a single occurrence.

For example, the below are all the same path as far as PoSh (Core) is concerned:
D:\test\data\test.txt
d:test/data/test.txt
d:\\\\\\\\test///////data\\\\test.txt
d:\\\\\\\\test//\\\\data\/\/\/\/test.txt

It makes this aspect of PoSh scripts OS agnostic ... something they got exactly right :Thmbsup:

ewemoa

  • Honorary Member
  • Joined in 2008
  • **
  • Posts: 2,897
    • View Profile
    • Donate to Member
Did some testing, though not with Powershell Core.  When launched from a Powershell terminal, the initial dialog wasn't behind any windows, but it didn't have focus.

The generated SENNHEISER ".csv" file I looked at didn't have an extra blank line between the header and the rest of the data.  IIRC, the original script puts a blank line between the header and the data.  Don't know if that makes any difference.

Other than that, it seemed pretty good to me.

Could avoid the GUI altogether and revert to a series of Read-Host prompt/answer inputs plus include the ability to run as a standard command if all parameters are fulfilled on the command line.

Would be the quickest way to make it portable.

I guess there could be a GUI wrapper around this -- in fact, there could be platform-specific wrappers.

W.r.t. filepaths, PowerShell (Core) is pretty agnostic when it comes to using / or \ - either will do, plus it sees multiple occurrences, (eg. ////), as just a single occurrence.

For example, the below are all the same path as far as PoSh (Core) is concerned:
D:\test\data\test.txt
d:test/data/test.txt
d:\\\\\\\\test///////data\\\\test.txt
d:\\\\\\\\test//\\\\data\/\/\/\/test.txt

It makes this aspect of PoSh scripts OS agnostic ... something they got exactly right :Thmbsup:


Nice.  I wouldn't be surprised if some cross-platform projects start using Powershell Core scripts instead of maintaining separate .bat and .sh files.  Perhaps some do already, though perhaps Powershell Core isn't yet installed on that many non-Windows systems...