none
Clean up older version & Deploying 365 proplus x64 Powershell script RRS feed

  • Question

  • The company I work for is trying to get all their systems to O365 64-bit. The problem we have is, that they every version of office is in their environment from Office 97 to 2016 and some 365 32-bit. They had the starts of a PowerShell script that remove just office 2016 which I have grown into something to handle every version. I am running into some issues with it and want to see if the community can help me see my faults in my design. We are deploying this out via LANDesk using system account to install in the background. I have also been instructed to record and remove every version of Project and Visio. Last, I have been told I need to re-install SFB-64 on a system if they had any flavor of SFB before the upgrade. So, here is a list of the issues:

    1. Does not always detect office 365 or other office Professional versions installed so they can be written to the log

    2. Office 365 setup.exe will not return an exit code for error caching, keep giving 0 no matter what i try.

    3. Skype FB will not always be detected and remove first, so it can be checked that it existed to be installed later.

    4. Even know I tell to remove all MSI it sometimes fails to remove Visio or Project 2013, but I don't get exit codes

    I am looking for suggestion, feel free to rip the code apart. It is currently working 75% of the time, when it runs on a system that had only one version of office and nothing else.

    #Used to:
    #1. Detect Visio and Project Versions installed and writes to log and a .txt file
    #2. Detect your version of Skype for business and removes it
    #3 Removes Office 2003 to 2007 via VBS scrubber
    #4. Tags the log if it finds Office 2010 or 2013
    #5. Run the C2R setup to remove all C2R and MSI installs currently on system
    #6. Install Office 365 X64 via C2R setup config
    #7. Installs Skype for business X64 back if they had it
    
    #System Variables
    $ScriptName = [io.path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name)
    $CurrentDirectory = split-path -parent  $MyInvocation.MyCommand.Path
    $LogDir = "$ENV:SystemDrive\Logs"
    $LogFile = "$LogDir\$scriptname.log"
    $ProcessID = [Diagnostics.Process]::GetCurrentProcess().ID
    $ProcessUserName = ((Get-WmiObject -Class Win32_Process | Where-Object {$_.ProcessID -EQ $ProcessID}).GetOwner()).User
    #New installations Components
    $Office64bit = "\\*********\******\O365S\Production\setup.exe"
    $Office64Arg1 = "/configure \\******\****\O365S\Production\Remove-O365X64.xml"
    $Office64Arg2 = "/configure \\********\*****\O365S\Production\Install_O365_64bit.xml"
    $Skype64bitArgs = "/configure \\********\*****\O365S\Production\Install-SkypeFBX64.xml"
    $ADBMSI = "\\********\******\O365S\Production\AccessDB-Engine\AceRedist.msi"
    #Removal tools
    $RemovalTools = "\\******\******\O365S\Production\LegacyRemovalTools"
    $SkypeMSI1 = "\\******\******\O365S\Production\LegacyRemovalTools\Skype-MSI-x86\setup.exe" #look at add it to a networkshare
    $SkypeMSI2 = "\\******\******\O365S\Production\LegacyRemovalTools\Skype-Msi-x64\setup.exe"
    $SkypeRemoverArg1 = "/configure \\********\******\O365S\Production\Remove-SkypeFB-C2R.xml"
    $SkypeRemoverArg2 = "\\********\*******\O365S\Production\Remove-SkypeFB-MSI.xml"
    $ProVisRemover = "\\******\*******\O365S\Production\Remove-MSI.xml"
    #Installer Variables
    $InstallSkype = 0
    $Runcount = 0
    $InstallADB = 0
    #Functions to log install status
    Function script:Log
    {
      [CmdletBinding()]
      Param ([String]$File,[String]$Data)
      $LogOutput = '"Timestamp:"' + (Get-Date -Format MM-dd-yyyy) + '-"' + (Get-Date -Format HH:mm:ss) + '" Ran by:"' + $ProcessUserName + '<!Logged-->"' + $Data + '" ProcessID:"' + $ProcessID + '">'
      Out-File -FilePath $LogFile -Append -NoClobber -InputObject $LogOutput -Encoding ASCII
    }
    #Log Dir maintenance
    If (!(Test-Path -Path $LogDir))
    {
      New-Item -Path $LogDir -ItemType Directory -Force
    }
    #Log File maintenance
    If (Test-Path -Path $LogFile)
    {
        If ((Get-Item $Logfile).Length -gt 2KB)
        {
            Rename-Item $Logfile $Logfile".bak" -Force
        }
        Else
        {
            Remove-Item -Path $LogFile
        }
    }
    #-----------------------------------------------------------------------------------
    #Detect for pending reboot
    #look at registry key call pendingfilerename if it is null then a reboot is need and they must restart first.
    #HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations
    $Restart = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name "PendingFileRenameOperations"
    $Restart = $Restart.PendingFileRenameOperations
    If ( $Restart -ne $Null)
    {
        log -File $LogFile -Data "System needs to restart and apply updates before running installer"
        [System.Windows.MessageBox]::Show('System has a pending restart, Restart before running this install again.','System Restart Detection') #Does not work as system?? 
        [Environment]::Exit(1)
    }
    Else
    {
        log -File $LogFile -Data "No System Restart needed"
    }
    #-------------------------------------------------------------------------------------------------
    #Disables & Stops the Interactive Detection Services on Win7 PC's
    if ([System.Environment]::OSVersion.Version.major -eq "6")
    {
        log -File $LogFile -Data "System is WIndows 7 & stopping UIO service"
        Set-Service UI0Detect -StartupType Disabled
        Get-Service UI0Detect | Where-Object {$_.status -eq 'Running'} | Stop-Service
        Start-Sleep -Seconds 2
        log -File $LogFile -Data "UIO Service has been stopped"
    }
    #-------------------------------------------------------------------------------------------------
    #Finds Visio version registy and stores it as a varible
    log -File $LogFile -Data "Seaching registry for Visio"
    $Visio = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall |
    Get-ItemProperty | Where-Object {$_.DisplayName -match "Visio*" } | Select-Object -Property DisplayName, UninstallString
    Start-Sleep -Seconds 5
    If ($Visio -ne $Null)
    {
        $Visio.DisplayName | Set-Content "$LogDir\Installed-Visio.log"
        ForEach ($Vis in $Visio) 
        {
            If (($Vis.DisplayName -like "Microsoft Visio Standard*") -or ($Vis.DisplayName -like "Microsoft Visio Professional*") -or ($Vis.DisplayName -like "Microsoft Office Visio Standard*") -or ($Vis.DisplayName -like "Microsoft Office Visio Professional*") -or ($Vis.DisplayName -like "Microsoft Office Visio 2010*") -and ($Vis.DisplayName -notmatch "Compatibility Pack"))
                {
                    $DN = $Vis.DisplayName
                    $uninst = $Vis.UninstallString
                    log -File $LogFile -Data "Found $DN installed on system, now uninstalling it."
                    If (!($uninst -like "Msiexec.exe*"))
                    {   
                        log -File $LogFile -Data "Remove with config file."
                        Start-Process cmd -ArgumentList "/c $uninst /config $ProVisRemover" -Wait -NoNewWindow
                        Break
                    }
                    else 
                    {
                        log -File $LogFile -Data "Remove with MSIEXEC."
                        Start-Process cmd -ArgumentList "/c $uninst /quiet /norestart" -Wait -NoNewWindow
                        Break
                    }
                    log -File $LogFile -Data "Finished uninstalling $DN"
                }
        }
    }
    Else
    {
        log -File $LogFile -Data "No instance of Microsoft Visio found"
    }
    #-------------------------------------------------------------------------------------------------
    #Finds Project version registy and stores it as a varible
    log -File $LogFile -Data "Seaching registry for Project"
    $Project = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall  |
    Get-ItemProperty | Where-Object {$_.DisplayName -match "Project" } | Select-Object -Property DisplayName, UninstallString
    Start-Sleep -Seconds 5
    #Uninstall the version of Project found
    If ($Project -ne $Null)
    {
        $Project.DisplayName | Set-Content "$LogDir\Installed-Project.log"
        ForEach ($Pro in $Project) 
        {
            If (($Pro.DisplayName -like "Microsoft Project Standard*") -or ($Vis.DisplayName -like "Microsoft Project Professional*") -or ($Vis.DisplayName -like "Microsoft Office Project Standard*") -or ($Vis.DisplayName -like "Microsoft Office Project Professional*") -and ($Pro.DisplayName -notmatch "Compatibility Pack")) 
            {
                 $DN = $Pro.DisplayName
                 $uninst = $Pro.UninstallString
                 log -File $LogFile -Data "Found $DN installed on system, now uninstalling it."
                 If (!($uninst -like "Msiexec.exe*"))
                 {
                     log -File $LogFile -Data "Remove with config file."
                     Start-Process cmd -ArgumentList "/c $uninst /config $ProVisRemover" -Wait -NoNewWindow
                     Break
                 }
                 else 
                 {
                     log -File $LogFile -Data "Remove with MSIEXEC."
                     Start-Process cmd -ArgumentList "/c $uninst /quiet /norestart" -Wait -NoNewWindow
                     Break
                 }
                 log -File $LogFile -Data "Finished uninstalling $DN"
            }
        }
    }
    Else
    {
        log -File $LogFile -Data "No instance of Microsoft Project found"
    }
    #------------------------------------------------------------------------------------------------
    #Remove Skype for Business 
    #Moved to using network share source files for uninstallers instead of files on PC
    log -File $LogFile -Data "Looking for any version of Skype installed on the system"
    $Skype = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall  |
    Get-ItemProperty | Where-Object {$_.DisplayName -match "Skype" } | Select-Object -Property DisplayName, UninstallString
    Start-Sleep -Seconds 5
    If (!($Skype -eq $Null))
    {
        log -File $LogFile -Data "Found Skype installed the system. Closing app and uninstalling it"
        Start-Process -FilePath cmd.exe -ArgumentList "/c TASKKILL /IM Lync*"
        Stop-Process -Name "Lync*" -Force
        $Skype.DisplayName | Set-Content "$LogDir\Installed-Skype.log"
        ForEach ($ver in $Skype) 
        {     
            #C2R                                               
            If ($ver.DisplayName -Match "Skype for Business 2016")
            {
                $InstallSkype = 1
                Try
                {
                    $DN = $ver.DisplayName
                    log -File $LogFile -Data "Found $DN installed and running C2R uninstaller"
                    Start-Process -FilePath $Office64bit -ArgumentList $SkypeRemoverArg1 -wait -NoNewWindow -ErrorAction Continue
                    Remove-Item -Path '"C:\Users\Public\Desktop\Skype for Business.lnk"' -Force -Recurse
                    Remove-Item -Path '"C:\Users\Public\Desktop\Skype for Business 2016.lnk"' -Force -Recurse
                    Break
                }
                Catch
                {
                    $($PSItem.ToString())
                    log -File $LogFile -Data "Error while Uninstalling Skype FB C2R, with error code $PSItem"
                    [Environment]::Exit(75)
                }
            }
            #MSI
            elseif (($ver.DisplayName -Match "Skype for Business Basic") -or ($ver.DisplayName -match "Skype for Business Entry"))
            {
                $InstallSkype = 1
                Try
                {   
                    $DN = $ver.DisplayName
                    log -File $LogFile -Data "Found $DN installed and uninstalling x32 version via config file"
                    Start-Process -FilePath $SkypeMSI1 -ArgumentList "/uninstall LYNCENTRY /dll OSETUP.DLL /config $SkypeRemoverArg2" -Wait -NoNewWindow -ErrorAction Continue
                    Remove-Item -Path '"C:\Users\Public\Desktop\Skype for Business.lnk"' -Force -Recurse
                    Remove-Item -Path '"C:\Users\Public\Desktop\Skype for Business 2016.lnk"' -Force -Recurse
                }
                Catch
              
                {
                    $($PSItem.ToString())
                    log -File $LogFile -Data "Error while Uninstalling Skype FB MSI, with error code $PSItem"
                    [Environment]::Exit(75)
                }
                try 
                {
                    $DN = $ver.DisplayName
                    log -File $LogFile -Data "Found $DN installed and uninstalling x64 bit version via config file"
                    Start-Process -FilePath $SkypeMSI2 -ArgumentList "/uninstall LYNCENTRY /dll OSETUP.DLL /config $SkypeRemoverArg2" -Wait -NoNewWindow -ErrorAction Continue
                    Remove-Item -Path '"C:\Users\Public\Desktop\Skype for Business.lnk"' -Force -Recurse
                    Remove-Item -Path '"C:\Users\Public\Desktop\Skype for Business 2016.lnk"' -Force -Recurse
                    Break
                }
                catch 
                {
                    $($PSItem.ToString())
                    log -File $LogFile -Data "Error while Uninstalling Skype FB MSI, with error code $PSItem"  
                    [Environment]::Exit(75)  
                }
                try 
                {
                    $uninst = $ver.UninstallString
                    $DN = $Ver.DisplayName
                    log -File $LogFile -Data "Uninstalling $DN using uninstall string method"
                    Start-Process -FilePath cmd.exe -ArgumentList "/c $uninst" -Wait -NoNewWindow -ErrorAction Continue
                    Remove-Item -Path '"C:\Users\Public\Desktop\Skype for Business.lnk"' -Force -Recurse
                    Remove-Item -Path '"C:\Users\Public\Desktop\Skype for Business 2016.lnk"' -Force -Recurse
                    Break
                }
                catch 
                {
                    $($PSItem.ToString())
                    log -File $LogFile -Data "Error while Uninstalling Skype FB MSI, with error code $PSItem"
                    [Environment]::Exit(75)    
                }
            }
            elseif ((Test-Path -path '"C:\Program Files\Microsoft Office\root\Office16\lync.exe"') -or (Test-Path -path '"C:\Program Files (x86)\Microsoft Office\root\Office16\lync.exe"'))
            {
                #Lync Click 2 Run was found and will be removed later in the script
                $InstallSkype = 1
                log -File $LogFile -Data "A version a Lync was detected and will be remove and Skype will be installer later"
            }
            Else
            {
                log -File $LogFile -Data "$ver.DisplayName was found, but we can't uninstall it"
            }
        }
    }
    Else
    {
        log -File $LogFile -Data "No instance of Microsoft Skype was found on this system"
    }
    #-------------------------------------------------------------------------------------------------
    #Detect Office 2010 Access Data Base connector
    $2010AD = Get-ChildItem -Path HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall  |
    Get-ItemProperty | Where-Object {$_.DisplayName -like "*Access database engine 2010*" } | Select-Object -Property DisplayName, UninstallString
    If ($2010AD -eq $null)
    {
        log -File $LogFile -Data "No Office 2010 Access Data Base Engine was found on this system."
    }
    Else
    {
        $InstallADB = 1 # install x64 Access Data Base 2007 Engine
        $2010ADDN = $O2010AD.DisplayName.GetValue(0)
        $uninst = '"{90140000-00D1-0409-0000-0000000FF1CE}"'
        log -File $LogFile -Data "Found Office 2010 Access Data Base Engine installed with product ID: $2010ADDN"
        Start-Process cmd -ArgumentList "/c MsiExec.exe /X $uninst /quiet /norestart" -Wait -NoNewWindow
        log -File $LogFile -Data "Finished uninstalling $2010ADDN"
    }
    #-------------------------------------------------------------------------------------------------
    #Detect Office 2007 Access Data Base connector
    $2007AD = Get-ChildItem -Path HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall  |
    Get-ItemProperty | Where-Object {$_.DisplayName -like "*Access database engine 2007*" } | Select-Object -Property DisplayName, UninstallString
    If ($2007AD -eq $null)
    {
        log -File $LogFile -Data "No Office 2007 Access Data Base Engine was found on this system."
    }
    Else
    {
        $InstallADB = 1 # install x64 Access Data Base 2007 Engine
        $2007ADDN = $O2007AD.DisplayName.GetValue(0)
        $uninst = '"{90120000-00D1-0409-0000-0000000FF1CE}"'
        log -File $LogFile -Data "Found Office 2007 Access Data Base Engine installed with product ID: $2007ADDN"
        Start-Process cmd -ArgumentList "/c MsiExec.exe /X $uninst /quiet /norestart" -Wait -NoNewWindow
        log -File $LogFile -Data "Finished uninstalling $2007ADDN"
    }
    #-------------------------------------------------------------------------------------------------
    #Remove office 97
    #Only 27 machines going to do manually
    #$O97X64 = 'C:\Program Files\Microsoft Office\Office97'
    #$O97X32 = 'C:\Program Files (x86)\Microsoft Office\Office97'
    #If ((Test-Path -Path $O97X32) -or (Test-Path -Path $O97X64))
    #Start-Process -FilePath RemovalTools\OFFCLN.exe -ArgumentList ("/A /Q /L C:\Logs\O97.log")
    #-------------------------------------------------------------------------------------------------
    #Remove office 2003
    $O2003X64 = 'C:\Program Files\Microsoft Office\Office11'
    $O2003X32 = 'C:\Program Files (x86)\Microsoft Office\Office11'
    If ((Test-Path -Path $O2003X32) -or (Test-Path -Path $O2003X64))
    {
        log -File $LogFile -Data "Detected Office 2003 files, Starting Uninstaller of Office 2003 Suite"
        Start-Process -FilePath CScript.exe -ArgumentList ("//B //nologo $RemovalTools\office-2003.vbs All /force /OSE /Quiet /Log C:\Logs\O2003") -wait -NoNewWindow
        log -File $LogFile -Data "Finshed removing Office 2003 from system"
        Remove-Item -Path $O2003X32 -Force -Recurse
        Remove-Item -Path $O2003X64 -Force -Recurse
    }
    #-------------------------------------------------------------------------------------------------
    #Office 2007 remover
    $O2007X64 = 'C:\Program Files\Microsoft Office\Office12'
    $O2007X32 = 'C:\Program Files (x86)\Microsoft Office\Office12'
    #If ($O2007 -isnot $null)
    If ((Test-Path -Path $O2007X32) -or (Test-Path -Path $O2007X64))
    {
        log -File $LogFile -Data "Detected Office 2007 files, Starting Uninstaller of Office 2003 Suite"
        Start-Process -FilePath CScript.exe -ArgumentList ("//B //nologo $RemovalTools\office-2007.vbs All /force /OSE /Quiet /Log C:\Logs\O2007") -wait -NoNewWindow
        log -File $LogFile -Data "Finshed removing Office 2007 from system"
        Remove-Item -Path $O2007X32 -Force -Recurse
        Remove-Item -Path $O2007X64 -Force -Recurse
    } 
    #-------------------------------------------------------------------------------------------------
    #Detect Version of Office the system
    $Office = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall  | 
    Get-ItemProperty | Where-Object {$_.DisplayName -like "*Office Professional*" } | Select-Object -Property DisplayName
    Start-Sleep -Seconds 5
    If ($Null -eq $Office)
    {
        log -File $LogFile -Data "No Office Professional Plus was found on this system."
    }
    Else
    {
        $OfficeDN = $Office.DisplayName
        log -File $LogFile -Data "Found Office with Product ID: $OfficeDN installed and it will be uninstalled"
    }
    #--------------------------------------------------------------------------------------------
    #Detect O365 C2R
    $O365 = Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall  | 
    Get-ItemProperty | Where-Object {$_.DisplayName -like "*Office 365*" } | Select-Object -Property DisplayName
    Start-Sleep -Seconds 5
    If ($O365 -eq $null)
    {
        log -File $LogFile -Data "No Office 365 ProPlus was found on this system."
    }
    Else
    {
        $O365DN = $O365.DisplayName
        log -File $LogFile -Data "Found $O365DN installed and it will be uninstalled"
    }
    #---------------------------------------------------
    #Removes all office products from 2010 to 365 ProPlus
    do 
    {
        log -File $LogFile -Data "Removing all Office 2010 to 365 ProPlus along with any Project & Visio installs"
        [int]$Task = (Start-Process -FilePath $Office64bit -ArgumentList $Office64Arg1 -Wait -NoNewWindow -ErrorAction Continue).ExitCode
        if ($Task -ne 0)
        {
            $($PSItem.ToString())
            log -File $LogFile -Data "Error while Uninstalling O365, with error code $PSItem"
            $Runcount ++
        }
    } until (($Task -EQ 0) -or ($Runcount -le 3))
    log -File $LogFile -Data "Finished uninstalling all office products off this system"
    Start-Sleep -Seconds 15  #To allow the click 2 run service to shut down and restart
    #------------------------------------------------------------------------------------------------
    #Installs Office 365 x64 on the local System    
        log -File $LogFile -Data "Installing O365 Click to Run X64"
        try 
        {
            Start-Process -FilePath $Office64bit -ArgumentList $Office64Arg2 -Wait -NoNewWindow -ErrorAction Continue
            log -File $LogFile -Data "Finshed Installing O365 Click to Run X64"
        }
        catch 
        {
            $($PSItem.ToString())
            log -File $LogFile -Data "Error while Installing O365 Click to Run X64, with error code $PSItem"
            [Environment]::Exit(75)
        }
    #-------------------------------------------------------------------------------------------
    #Clean up of old files
    log -File $LogFile -Data "Cleaning up old office directories"
    Remove-Item -Path "C:\Program Files (x86)\Microsoft Office" -Force -Recurse
    Remove-Item -Path "C:\Program Files (x86)\Microsoft Office 2010" -Force -Recurse
    Remove-Item -Path "C:\Program Files\Microsoft Office\Office15" -Force -Recurse
    Remove-Item -Path "C:\Program Files\Microsoft Office\Office14" -Force -Recurse
    #-------------------------------------------------------------------------------------------------
    #Installing Skype back on the system if they had but in X64 bit 
     If ($InstallSkype -eq 1) 
     {
        try 
        {
            log -File $LogFile -Data "Installing Skype FB back on the system"
            Start-Process -FilePath $Office64bit -ArgumentList $Skype64bitArgs -Wait -NoNewWindow -ErrorAction Continue
            log -File $LogFile -Data "Installed Skype FB 2016 X64 on this machine"
        }
        catch 
        {
            $($PSItem.ToString())
            Log -file $Logfile -Data "Failed to install Skype for Business X64 due to $PSItem"  
            [Environment]::Exit(75) 
        }
     }
    #-----------------------------------------------------------------------------------------
     #Installing Access Data Base Engine back on the system if they had but in.
     If ($InstallADB -eq 1) 
     {
        try 
        {
            log -File $LogFile -Data "Installing Access Data Base 2007 back on the system for Sharepoint"
            Start-Process -FilePath cmd -ArgumentList "/c MsiExec.exe /i $ADBMSI /quiet /norestart" -Wait -NoNewWindow -ErrorAction Continue
            log -File $LogFile -Data "Installed Access Data Base 2007 on this machine"
        }
        catch 
        {
            $($PSItem.ToString())
            Log -file $Logfile -Data "Failed to install Access Data Base 2007 due to $PSItem" 
            [Environment]::Exit(75)  
        }
     }
    #-----------------------------------------------------------------------------------------------------------
    #Final line in log and return code to Landesk / SCCM
    log -File $LogFile -Data "The script has finished attempting to install O365X64 on to your system."
    [Environment]::Exit(0)

    Thank you for helping out, as I am still learning everyday with powershell.


    Alec B Moeller

    • Moved by Bill_Stewart Thursday, December 13, 2018 3:30 PM This is not "debug/fix/rewrite my script for me" forum
    Friday, September 21, 2018 4:22 PM