<# This script will... - Copy and then install the Arsenal Image Mounter (AIM) software - Copy the CreateRAMDisk.ps1 PowerShell script - Create the Scheduled Tasks Script variables: - Setting the $CreateTasksOnly value to True will skip the installion and only create the Scheduled Tasks. - Setting the $CreateMainTaskOnly value to True will create the main (1st) Scheduled Task only. - Setting the $EnableMainTask value to True will Enable the main (1st) Scheduled Task. It's Disabled by default. Script name: Install.ps1 Release 1.0 Written by Jeremy Saunders (jeremy@jhouseconsulting.com) 17th February 2024 #> #------------------------------------------------------------- param( [switch]$CreateTasksOnly, [switch]$CreateMainTaskOnly, [switch]$EnableMainTask ) # Set Powershell Compatibility Mode Set-StrictMode -Version 2.0 # Enable verbose, warning and error mode $VerbosePreference = 'Continue' $WarningPreference = 'Continue' $ErrorPreference = 'Continue' #------------------------------------------------------------- Write-Verbose "Setting Arguments" -Verbose $StartDTM = (Get-Date) # Get the current script path $ScriptPath = {Split-Path $MyInvocation.ScriptName} $ScriptPath = $(&$ScriptPath) $Vendor = "Arsenal Recon" $Product = "Arsenal Image Mounter" $PackageName = "ArsenalImageMounter" $Version = "3.11.290" $InstallerType = "exe" $LogPS = "${env:SystemRoot}" + "\Temp\$Vendor $Product $Version PS Wrapper.log" Start-Transcript $LogPS # Bypass the "Open File Security Warning" dialog box. # For more information refer to http://support.microsoft.com/kb/889815 $env:SEE_MASK_NOZONECHECKS = 1 $InstallFolder = "${env:ProgramFiles}\Arsenal Image Mounter" $PrerequisiteMet = $False If ($CreateTasksOnly) { $PrerequisiteMet = $True } $CreateTask = $False # Create the folder structure If (-not(Test-Path -Path "$InstallFolder")) { Write-Verbose "Creating the Folder Path: `"$InstallFolder`"" -Verbose New-Item -Path "$InstallFolder" -ItemType Directory | Out-Null } If ($CreateTasksOnly -eq $False) { # Push the current location onto a location stack and then change the current location to the location specified Push-Location "$ScriptPath\$Version" # Copy the files into place copy-item -path "$ScriptPath\$Version\*" -Destination "$InstallFolder\" -Recurse -Force -Verbose # Change the current location back to the location most recently pushed onto the stack, which will be defined by the $ScriptPath variable Pop-Location # Push the current location onto a location stack and then change the current location to the location specified Push-Location "$InstallFolder" If (Test-Path "${Env:ProgramFiles(x86)}\AutoIt3\AutoItX\AutoItX3.psd1") { Write-Verbose "Starting Installation of $Vendor $Product $Version" -Verbose (Start-Process "$PackageName.$InstallerType") # Import the module manfiest Import-Module "${Env:ProgramFiles(x86)}\AutoIt3\AutoItX\AutoItX3.psd1" $WindowCount = 0 #################################### # Wait for window and get the handle $WindowTitle = "Arsenal Image Mounter" $WindowText = "This application requires .NET Desktop Runtime" $Return = Wait-AU3Win -Title $WindowTitle -Text $WindowText -Timeout 5 If ($Return -eq 1) { $WindowCount ++ # Get the handle $winHandle = Get-AU3WinHandle -Title $WindowTitle -Text $WindowText write-verbose "Progress:" -verbose write-verbose "- Window Title: $WindowTitle" -verbose write-verbose "- Window Text: $WindowText" -verbose write-verbose "- Window Count: $WindowCount" -verbose # Activate the window Show-AU3WinActivate -WinHandle $winHandle # Send some keystrokes Send-AU3Key "!n" write-warning "Please install the .NET Desktop Runtime prerequisite" } Else { $PrerequisiteMet = $True # Wait for window and get the handle $WindowTitle = "StartupWindow" $WindowText = "" $WindowCount ++ # Wait for window and get the handle Wait-AU3Win -Title $WindowTitle -Text $WindowText $winHandle = Get-AU3WinHandle -Title $WindowTitle -Text $WindowText write-verbose "Progress:" -verbose write-verbose "- Window Title: $WindowTitle" -verbose write-verbose "- Window Text: $WindowText" -verbose write-verbose "- Window Count: $WindowCount" -verbose # Activate the window Show-AU3WinActivate -WinHandle $winHandle # Send some keystrokes Send-AU3Key "{TAB 5}" Send-AU3Key "{ENTER}" #################################### $WindowTitle = "Arsenal Image Mounter" $WindowText = "This application requires a virtual SCSI miniport driver to create virtual disks" $Return = Wait-AU3Win -Title $WindowTitle -Text $WindowText -Timeout 5 If ($Return -eq 1) { $WindowCount ++ # Wait for window and get the handle Wait-AU3Win -Title $WindowTitle -Text $WindowText $winHandle = Get-AU3WinHandle -Title $WindowTitle -Text $WindowText write-verbose "Progress:" -verbose write-verbose "- Window Title: $WindowTitle" -verbose write-verbose "- Window Text: $WindowText" -verbose write-verbose "- Window Count: $WindowCount" -verbose # Activate the window Show-AU3WinActivate -WinHandle $winHandle # Send some keystrokes Send-AU3Key "!y" #################################### # Wait for window and get the handle $WindowTitle = "Driver Setup" $WindowText = "" $WindowCount ++ # Wait for window and get the handle Wait-AU3Win -Title $WindowTitle -Text $WindowText $winHandle = Get-AU3WinHandle -Title $WindowTitle -Text $WindowText write-verbose "Progress:" -verbose write-verbose "- Window Title: $WindowTitle" -verbose write-verbose "- Window Text: $WindowText" -verbose write-verbose "- Window Count: $WindowCount" -verbose # Activate the window Show-AU3WinActivate -WinHandle $winHandle # Send some keystrokes Send-AU3Key "{ENTER}" } #################################### # Wait for window and get the handle $WindowTitle = "Arsenal Image Mounter" $WindowText = "" $WindowCount ++ # Wait for window and get the handle Wait-AU3Win -Title $WindowTitle -Text $WindowText $winHandle = Get-AU3WinHandle -Title $WindowTitle -Text $WindowText write-verbose "Progress:" -verbose write-verbose "- Window Title: $WindowTitle" -verbose write-verbose "- Window Text: $WindowText" -verbose write-verbose "- Window Count: $WindowCount" -verbose # Activate the window Show-AU3WinActivate -WinHandle $winHandle # Send some keystrokes Send-AU3Key "!f" Send-AU3Key "{UP 1}" Send-AU3Key "{ENTER}" #################################### write-verbose "Disabling unnecessary services..." -verbose write-verbose "- VHD image file access driver" -verbose Get-Service -Name vhdaccess | Stop-Service -Force Set-Service -Name vhdaccess -StartupType Disabled write-verbose "- AWE memory allocation driver" -verbose Get-Service -Name awealloc | Stop-Service -Force Set-Service -Name awealloc -StartupType Disabled } } # Change the current location back to the location most recently pushed onto the stack, which will be defined by the $ScriptPath variable Pop-Location } If ($PrerequisiteMet) { Write-Verbose "Customization" -Verbose # Copy the script in place to create the RAM Disk from a Scheduled Task If (TEST-PATH "$ScriptPath\CreateRAMDisk.ps1") { $CreateTask = $True copy-item -path "$ScriptPath\CreateRAMDisk.ps1" -Destination "$InstallFolder\" -Recurse -Force -Verbose } # Create the Scheduled Task If ($CreateTask) { # Scheduled Task 1 $ScheduledTask1 = New-Object -TypeName PSObject -Property @{ "TaskName" = "Create a RAM Disk with fixed memory allocation at Startup" "TaskDescription" = "This task will create a RAM Disk with fixed memory allocation at computer startup based on the total physical RAM installed. As it allocates the RAM dynamically, it will not consume RAM until it is used." "TaskCommand" = @(Get-Command powershell.exe)[0].Definition "TaskScript" = "$InstallFolder\CreateRAMDisk.ps1" "TaskArguments" = "-Action:Create" "EnableTask" = $False "AddTrigger" = $True "AllowUsersExecute" = $False } If ($EnableMainTask) { $ScheduledTask1.EnableTask = $True } If ($CreateMainTaskOnly -eq $False) { # Scheduled Task 2 $ScheduledTask2 = New-Object -TypeName PSObject -Property @{ "TaskName" = "Create a 4GB RAM Disk with fixed memory allocation" "TaskDescription" = "This task will create an 4GB RAM Disk with fixed memory allocation." "TaskCommand" = @(Get-Command powershell.exe)[0].Definition "TaskScript" = "$InstallFolder\CreateRAMDisk.ps1" "TaskArguments" = "-Action:Create -Size:4G" "EnableTask" = $True "AddTrigger" = $False "AllowUsersExecute" = $True } # Scheduled Task 3 $ScheduledTask3 = New-Object -TypeName PSObject -Property @{ "TaskName" = "Create a 8GB RAM Disk with fixed memory allocation" "TaskDescription" = "This task will create an 8GB RAM Disk with fixed memory allocation." "TaskCommand" = @(Get-Command powershell.exe)[0].Definition "TaskScript" = "$InstallFolder\CreateRAMDisk.ps1" "TaskArguments" = "-Action:Create -Size:8G" "EnableTask" = $True "AddTrigger" = $False "AllowUsersExecute" = $True } # Scheduled Task 4 $ScheduledTask4 = New-Object -TypeName PSObject -Property @{ "TaskName" = "Create a 16GB RAM Disk with fixed memory allocation" "TaskDescription" = "This task will create an 16GB RAM Disk with fixed memory allocation." "TaskCommand" = @(Get-Command powershell.exe)[0].Definition "TaskScript" = "$InstallFolder\CreateRAMDisk.ps1" "TaskArguments" = "-Action:Create -Size:16G" "EnableTask" = $True "AddTrigger" = $False "AllowUsersExecute" = $True } # Scheduled Task 5 $ScheduledTask5 = New-Object -TypeName PSObject -Property @{ "TaskName" = "Create a 24GB RAM Disk with fixed memory allocation" "TaskDescription" = "This task will create an 24GB RAM Disk with fixed memory allocation." "TaskCommand" = @(Get-Command powershell.exe)[0].Definition "TaskScript" = "$InstallFolder\CreateRAMDisk.ps1" "TaskArguments" = "-Action:Create -Size:24G" "EnableTask" = $True "AddTrigger" = $False "AllowUsersExecute" = $True } # Scheduled Task 6 $ScheduledTask6 = New-Object -TypeName PSObject -Property @{ "TaskName" = "Create a 32GB RAM Disk with fixed memory allocation" "TaskDescription" = "This task will create an 32GB RAM Disk with fixed memory allocation." "TaskCommand" = @(Get-Command powershell.exe)[0].Definition "TaskScript" = "$InstallFolder\CreateRAMDisk.ps1" "TaskArguments" = "-Action:Create -Size:32G" "EnableTask" = $True "AddTrigger" = $False "AllowUsersExecute" = $True } # Scheduled Task 7 $ScheduledTask7 = New-Object -TypeName PSObject -Property @{ "TaskName" = "Remove ALL existing RAM Disks" "TaskDescription" = "This task deletes ALL existing RAM Disks" "TaskCommand" = @(Get-Command powershell.exe)[0].Definition "TaskScript" = "$InstallFolder\CreateRAMDisk.ps1" "TaskArguments" = "-Action:Remove" "EnableTask" = $True "AddTrigger" = $False "AllowUsersExecute" = $False } # Create a hash table of Scheduled Tasks to be created $ScheduledTasksToCreate = @{ "Task1" = $ScheduledTask1 "Task2" = $ScheduledTask2 "Task3" = $ScheduledTask3 "Task4" = $ScheduledTask4 "Task5" = $ScheduledTask5 "Task6" = $ScheduledTask6 "Task7" = $ScheduledTask7 } } Else { # Create a hash table of Scheduled Tasks to be created $ScheduledTasksToCreate = @{ "Task1" = $ScheduledTask1 } } ForEach ($key in $ScheduledTasksToCreate.keys) { $taskName = $ScheduledTasksToCreate.$key.TaskName $taskDescription = $ScheduledTasksToCreate.$key.TaskDescription $TaskCommand = $ScheduledTasksToCreate.$key.TaskCommand $TaskScript = $ScheduledTasksToCreate.$key.TaskScript $TaskArguments = $ScheduledTasksToCreate.$key.TaskArguments $TaskArguments = '-Executionpolicy bypass -Command "& ' + " '" + $TaskScript + "' " + $TaskArguments + '"' $EnableTask = $ScheduledTasksToCreate.$key.EnableTask $AddTrigger = $ScheduledTasksToCreate.$key.AddTrigger $AllowUsersExecute = $ScheduledTasksToCreate.$key.AllowUsersExecute write-verbose "Task Name: $($taskName)" -verbose write-verbose "- Description: $($taskDescription)" -verbose write-verbose "- Command: $($TaskCommand)" -verbose write-verbose "- Script: $($TaskScript)" -verbose write-verbose "- Arguments: $($TaskArguments)" -verbose # Create the TaskService object. Try { [Object] $service = new-object -com("Schedule.Service") If (!($service.Connected)){ Try { $service.Connect() # Get a folder to create a task definition in # This is actually the %SystemRoot%\System32\Tasks folder. $rootFolder = $service.GetFolder("\") # Delete the task if already present $ScheduledTasks = $rootFolder.GetTasks(0) $Task = $ScheduledTasks | Where-Object{$_.Name -eq "$TaskName"} If ($Task -ne $Null){ Try { $rootFolder.DeleteTask($Task.Name,0) # 'Success' } Catch [System.Exception]{ # 'Exception Returned' } } Else { # "Task Not Found" } # Create the new task $taskDefinition = $service.NewTask(0) If ($AddTrigger) { # Create a registration trigger with a trigger type of (8) at startup $triggers = $taskDefinition.Triggers $trigger = $triggers.Create(8) $trigger.Id = "BootTriggerId" $trigger.Enabled = $true } # Create the action for the task to execute. $Action = $taskDefinition.Actions.Create(0) $Action.Path = $TaskCommand $Action.Arguments = $TaskArguments $Action.WorkingDirectory = "" # Register (create) the task. $Settings = $taskDefinition.Settings # Set the Task Compatibility to V2 (Windows 7/2008R2) $Settings.Compatibility = 3 $Settings.AllowDemandStart = $true $Settings.StopIfGoingOnBatteries = $false $Settings.DisallowStartIfOnBatteries = $false $regInfo = $taskDefinition.RegistrationInfo $regInfo.Description = $taskDescription $regInfo.Author = $Env:Username # Note that the task is created as an XML file under the %SystemRoot%\System32\Tasks folder # 6 == Task Create or Update # 5 == A Local System, Local Service, or Network Service account is being used as a security context to run the task. $rootFolder.RegisterTaskDefinition($taskName, $taskDefinition, 6, "System", $null , 5) | out-null "Scheduled Task Created Successfully" If (!($EnableTask)) { $rootFolder.GetTasks(0) | Where-Object{$_.Name -eq "$TaskName"} | ForEach-Object { "Disabled task" $_.Enabled = $False } } If ($AllowUsersExecute) { If (TEST-PATH "${env:SystemRoot}\System32\Tasks\$taskName") { Write-Verbose "Giving Users read and execute access to be able to lanuch the `"$taskName`" task" -verbose $result = Invoke-Expression -command "icacls.exe `"${env:SystemRoot}\System32\Tasks\$taskName`" /grant:r `"BUILTIN\Users:(RX)`" /Q /C 2>&1" $result } } } Catch [System.Exception]{ "Scheduled Task Creation Failed" $ExitCode = 1 } } } Catch [System.Exception]{ "Scheduled Task Creation Failed" $ExitCode = 1 } } } } # Enable File Security Remove-Item env:\SEE_MASK_NOZONECHECKS Write-Verbose "Stop logging" -Verbose $EndDTM = (Get-Date) Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalSeconds) Seconds" -Verbose Write-Verbose "Elapsed Time: $(($EndDTM-$StartDTM).TotalMinutes) Minutes" -Verbose Stop-Transcript