- Overview
- Key Components
- Usage Instructions
- Understanding How the Script Works
- Common Issues and Troubleshooting
- Customizing the Script
- code
This tool is particularly useful for tasks that require repetitive data entry, such as inputting serial numbers, codes, or form data, without the need to manually copy and paste each item individually.
#Overview
- Sequential Pasting: Enables users to paste items from a list one after another by pressing a designated hotkey.
- Global Hotkeys: Implements system-wide hotkeys to control the script’s actions, such as pasting the next item, pausing/resuming the process, and quitting the script.
- User Interface: Runs silently in the background with minimal user interface interaction, displaying messages when necessary to inform the user of important events or errors.
#Key Components
-
Loading Required Assemblies
Add-Type -AssemblyName System.Windows.Forms
- Loads the necessary .NET assembly to access Windows Forms classes and methods, enabling features like message boxes and clipboard operations within the script.
-
Configuration Settings
$Config = @{ ListFilePath = "$HOME\Documents\list.txt" Hotkeys = @{ Paste = 'Control+F11' # Pause = 'Control+Shift+F11' # Updated hotkey to avoid conflicts Quit = 'Control+F12' } AutoTab = $false }
- ListFilePath: Specifies the path to the text file containing the items to be pasted. Users can modify this path to point to their desired file location.
- Hotkeys: Defines the global hotkeys for controlling the script:
- Paste: Pressing
Control+F11
triggers the script to paste the next item in the list. - Pause: (Commented out by default) Can be enabled to toggle pausing and resuming the pasting process.
- Quit: Pressing
Control+F12
exits the script.
- Paste: Pressing
- AutoTab: If set to
$true
, the script sends aTab
key after pasting each item, which is useful for moving to the next input field automatically.
-
Function
Show-Message
- A utility function that displays message boxes with customizable messages, titles, and icons. It uses Windows Forms to present information to the user, such as notifications or error messages.
-
Function
Load-ListItems
- Validates and loads the items from the specified list file. The function checks if the file exists and is not empty. It reads the contents into an array, ignoring any empty lines.
- If the file is not found or is empty, the function displays an error message and exits the script gracefully.
-
Function
Parse-Hotkeys
- Parses the hotkey strings defined in the configuration and converts them into modifier keys and virtual key codes that the Windows API can interpret.
- Associates each hotkey with a unique identifier (ID) required for registering the hotkeys with the system.
-
Hotkey Message Filter
- Implements a custom message filter using the
IMessageFilter
interface to intercept Windows messages, specificallyWM_HOTKEY
. - This allows the script to detect when the registered global hotkeys are pressed, even if the script’s window is not in focus.
- Implements a custom message filter using the
-
Function
Start-Paster
- The main function that encapsulates the script’s core logic:
- Initialization: Loads the list items and initializes variables such as the current index and pause state.
- Hotkey Registration: Registers the global hotkeys using Windows API functions
RegisterHotKey
andUnregisterHotKey
. - Hidden Form Creation: Creates an invisible Windows Form to handle message processing and to keep the script running.
- Hotkey Actions:
- Paste: When the paste hotkey is pressed, the script checks if it is not paused and pastes the next item:
- Copies the current item to the clipboard.
- Simulates a
Ctrl+V
key press to paste the item into the active application. - Optionally sends a
Tab
key ifAutoTab
is enabled. - Increments the index to move to the next item.
- If all items have been pasted, the script notifies the user and exits.
- Pause: (If enabled) Toggles the paused state and informs the user.
- Quit: Exits the script gracefully.
- Paste: When the paste hotkey is pressed, the script checks if it is not paused and pastes the next item:
- Cleanup: Unregisters hotkeys and removes message filters when the script is closed.
- The main function that encapsulates the script’s core logic:
-
Starting the Script
Start-Paster
- Invokes the main function to commence the sequential pasting process.
#Usage Instructions
Prerequisites:
- PowerShell Version: Ensure you are running PowerShell 5.0 or higher.
- Execution Policy: By default, PowerShell restricts script execution. You may need to adjust the execution policy to run this script:
- Open PowerShell as an administrator.
- Run
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
. - This allows you to run scripts you have written or downloaded from trusted sources.
Setup:
-
Prepare the List File:
- Create a text file at the path specified by
ListFilePath
(e.g.,C:\Users\YourName\Documents\list.txt
). - Add the items you wish to paste, placing each item on a new line.
- Create a text file at the path specified by
-
Configure the Script:
- Modify the
$Config
hashtable in the script if you wish to change file paths, hotkeys, or enable features likeAutoTab
orPause
.
- Modify the
Running the Script:
- Open PowerShell and navigate to the directory containing the script.
- Execute the script by typing
.\SequentialPaster.ps1
(replace with the script’s actual filename). - A message box will appear, confirming that the Sequential Paster is running.
Using the Hotkeys:
- Paste Next Item: Press
Control+F11
to paste the next item in your list. - Pause/Resume: If enabled, press the configured hotkey (e.g.,
Control+Shift+F11
) to pause or resume the pasting process. - Quit: Press
Control+F12
to stop the script.
Notes:
- If you reach the end of your list, the script will notify you that all items have been pasted and will exit automatically.
- If you attempt to paste while the script is paused, it will inform you that pasting is currently paused.
#Understanding How the Script Works
-
Sequential Processing:
- The script keeps track of the current item using an index. Each time you press the paste hotkey, it processes the next item in the array.
-
Global Hotkeys:
- Global hotkeys are registered with the Windows operating system, allowing the script to respond to key presses regardless of which application is currently active.
-
Clipboard Management:
- The script uses the Windows clipboard to transfer text. It copies the next item to the clipboard and then simulates a
Ctrl+V
key press to paste it.
- The script uses the Windows clipboard to transfer text. It copies the next item to the clipboard and then simulates a
-
Error Handling:
- The script includes error handling to manage issues such as missing or empty list files, hotkey registration failures, and attempting to paste beyond the end of the list.
#Common Issues and Troubleshooting
-
Hotkey Conflicts:
- If hotkey registration fails, the script will display an error message with an error code.
- Error Code 1409: Indicates that the hotkey is already in use by another application.
- Resolution: Modify the hotkeys in the
$Config.Hotkeys
hashtable to use a different combination.
- If hotkey registration fails, the script will display an error message with an error code.
-
Script Execution Policy Errors:
- If you receive an error about script execution being disabled, adjust your execution policy as outlined in the prerequisites.
-
Permissions:
- Running the script typically does not require administrative privileges. However, ensure that your user account has the necessary permissions to execute scripts and access the specified files.
#Customizing the Script
-
Changing Hotkeys:
- Update the hotkey combinations in the
$Config.Hotkeys
hashtable to suit your preferences. - Use key names recognized by
[System.Windows.Forms.Keys]
for compatibility.
- Update the hotkey combinations in the
-
Enabling AutoTab:
- Set
$Config.AutoTab
to$true
if you want the script to automatically send aTab
key after pasting each item.
- Set
-
Enabling Pause Functionality:
- Uncomment and configure the
Pause
hotkey in the configuration to enable pausing and resuming the pasting process.
- Uncomment and configure the
#code
# Sequential Paster.ps1 - Corrected Version with Proper Variable Scoping
# Load necessary assemblies
Add-Type -AssemblyName System.Windows.Forms
# Configuration
$Config = @{ ListFilePath = "$HOME\\Documents\\list.txt" Hotkeys = @{ Paste = 'Control+F11'
# Pause = 'Control+Shift+F11' # Updated hotkey to avoid conflicts
```
Quit = 'Control+F12'
}
AutoTab = $false
```
}
# Function to display messages
function Show-Message { param( \[string\]$Message, \[string\]$Title = "Sequential Paster", \[string\]$IconType = "Information" ) $icon = switch ($IconType.ToLower()) { "information" { \[System.Windows.Forms.MessageBoxIcon\]::Information } "error" { \[System.Windows.Forms.MessageBoxIcon\]::Error } "warning" { \[System.Windows.Forms.MessageBoxIcon\]::Warning } default { \[System.Windows.Forms.MessageBoxIcon\]::Information } } \[System.Windows.Forms.MessageBox\]::Show($Message, $Title, \[System.Windows.Forms.MessageBoxButtons\]::OK, $icon) | Out-Null }
# Validate and load items from the list file
function Load-ListItems { try { if (-not (Test-Path -Path $Config.ListFilePath)) { Show-Message "List file not found at:`n$($Config.ListFilePath)`nPlease create it and add items." "Error" "Error" exit } $ListItems = Get-Content -Path $Config.ListFilePath -Encoding UTF8 | Where-Object { $*.Trim() } if ($ListItems.Count -eq 0) { Show-Message "The list file is empty." "Error" "Error" exit } return $ListItems } catch { Show-Message "Error reading list file: $*" "Error" "Error" exit } }
# Parse hotkey strings into modifier keys and virtual key codes
function Parse-Hotkeys { param(\[hashtable\]$HotkeyConfig) $hotkeyMappings = @{} foreach ($key in $HotkeyConfig.Keys) { try { $hotkeyString = $HotkeyConfig\[$key\] $modifiers = 0 $keyCode = 0 $parts = $hotkeyString -split '+' foreach ($part in $parts) { switch ($part.ToLower()) { 'control' { $modifiers += 2 } 'shift' { $modifiers += 4 } 'alt' { $modifiers += 1 } default { $keyCode = \[int\]\[System.Windows.Forms.Keys\]::$part } } } $hotkeyMappings\[$key\] = @{ Modifiers = $modifiers KeyCode = $keyCode ID = \[System.Guid\]::NewGuid().GetHashCode() } } catch { Show-Message "Invalid hotkey configuration for '$key': $hotkeyString" "Error" "Error" exit } } return $hotkeyMappings }
# Implement the IMessageFilter interface for handling messages
Add-Type -ReferencedAssemblies "System.Windows.Forms" -TypeDefinition @" using System; using System.Windows.Forms;
public class HotkeyMessageFilter : IMessageFilter { public delegate void HotkeyPressedHandler(int hotkeyId); public event HotkeyPressedHandler HotkeyPressed;
```
public bool PreFilterMessage(ref Message m)
{
const int WM_HOTKEY = 0x0312;
if (m.Msg == WM_HOTKEY)
{
int hotkeyId = m.WParam.ToInt32();
if (HotkeyPressed != null)
{
HotkeyPressed.Invoke(hotkeyId);
}
return true;
}
return false;
}
```
} "@
# Main logic encapsulated in a function
function Start-Paster { $script:ListItems = Load-ListItems $script:CurrentIndex = 0 $script:IsPaused = $false
```
$Hotkeys = Parse-Hotkeys -HotkeyConfig $Config.Hotkeys
Add-Type -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true)]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
```
"@ -Name "NativeMethods" -Namespace "WinAPI"
```
$form = New-Object System.Windows.Forms.Form
$form.WindowState = 'Minimized'
$form.ShowInTaskbar = $false
# Register hotkeys
foreach ($hotkeyName in $Hotkeys.Keys) {
$hotkey = $Hotkeys[$hotkeyName]
$registered = [WinAPI.NativeMethods]::RegisterHotKey($form.Handle, $hotkey.ID, $hotkey.Modifiers, $hotkey.KeyCode)
if (-not $registered) {
$errorCode = [Runtime.InteropServices.Marshal]::GetLastWin32Error()
Show-Message "Failed to register hotkey '$hotkeyName'. Error code: $errorCode" "Error" "Error"
exit
}
}
# Create an instance of the message filter
$filter = New-Object HotkeyMessageFilter
# Add the message filter to the application
[System.Windows.Forms.Application]::AddMessageFilter($filter)
# Define the action when a hotkey is pressed
$filter.add_HotkeyPressed({
param($hotkeyId)
foreach ($hotkeyName in $Hotkeys.Keys) {
if ($Hotkeys[$hotkeyName].ID -eq $hotkeyId) {
switch ($hotkeyName) {
'Paste' {
if (-not $script:IsPaused) {
if ($script:CurrentIndex -lt $script:ListItems.Count) {
$item = $script:ListItems[$script:CurrentIndex]
try {
[System.Windows.Forms.Clipboard]::SetText($item)
[System.Windows.Forms.SendKeys]::SendWait('^v')
if ($Config.AutoTab) {
Start-Sleep -Milliseconds 50
[System.Windows.Forms.SendKeys]::SendWait('{TAB}')
}
$script:CurrentIndex++
} catch {
Show-Message "Error during paste: $_" "Error" "Error"
}
if ($script:CurrentIndex -ge $script:ListItems.Count) {
Show-Message "All items pasted." "Info" "Information"
$form.Close()
}
}
} else {
Show-Message "Pasting is paused." "Info" "Information"
}
}
'Pause' {
$script:IsPaused = -not $script:IsPaused
$status = if ($script:IsPaused) { 'Paused' } else { 'Resumed' }
Show-Message "Pasting $status." "Info" "Information"
}
'Quit' {
Show-Message "Quitting." "Info" "Information"
$form.Close()
}
}
break
}
}
})
# Form Closed event handler
$form.add_FormClosed({
# Unregister hotkeys
foreach ($hotkey in $Hotkeys.Values) {
[WinAPI.NativeMethods]::UnregisterHotKey($form.Handle, $hotkey.ID) | Out-Null
}
# Remove the message filter
[System.Windows.Forms.Application]::RemoveMessageFilter($filter)
[System.Windows.Forms.Application]::Exit()
})
# Show startup message
Show-Message "Sequential Paster is running.`nUse the configured hotkeys to control it." "Info" "Information"
# Start the application loop
[System.Windows.Forms.Application]::Run($form)
```
}
# Start the paster
Start-Paster