I have developed several scripts to remove unused profiles from machines with the exception of a few important accounts. Every script that I use always give me the same error when using the Remove-WmiObject, Remove-CimInstance, and .Delete(). I am certain that all of these scripts should work, but I receive the same error. Please see the below script and attached error. There is something wrong with my machine that is blocking me from using any of these functions. So my question: Is there anything I can do to get these functions to work for me or troubleshoot the issue? (I can attach other scripts and errors if needed)
Script:
$Admin = "Administrator","Public","Default","Administrator"
foreach($file in Get-ChildItem C:\Users\)
{
if ($file -in $Admin)
{
Write-Host = "`r`nUser account is" $file ". This is an Administrator Account, it will not be deleted."
}
else
{
Write-Host = "`r`nUser account is" $file ". Checking profiles age..."
$FileDate = (Get-item C:\Users\$file).CreationTime
Write-Host = $FileDate
$TestDate = (Get-Date).addDays(-30)
Write-Host = $TestDate
If ($FileDate -lt $TestDate)
{
Write-Host = "Since" $file "is older than 30 Days (" $FileDate ") it will be deleted."
$UserAccountPath = "C:\\Users\\$file"
$WMIQuery = "SELECT * FROM Win32_UserProfile WHERE localpath = '$UserAccountPath'"
$UserProfile = get-wmiobject win32_userprofile | Where-Object localpath -EQ $file.FullName
Remove-WmiObject -InputObject "$UserProfile"
}
else
{
Write-Host = "Since File is dated less than 30 days old (" $FileDate ") it will not need to be deleted."
}
}
}
Error:
Remove-WmiObject :
At line:28 char:17
+ Remove-WmiObject -InputObject "$UserProfile"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Remove-WmiObject], FileLoadException
+ FullyQualifiedErrorId : System.IO.FileLoadException,Microsoft.PowerShell.Commands.RemoveWmiObject
My past post might help for some background info: How to delete old profiles with script .
$sidToRemove = [System.Security.Principal.SecurityIdentifier]::new([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid, $null).ToString()
Get-WmiObject -Class Win32_UserProfile -Filter "SID = '$($sidToRemove)' AND SPECIAL = 'FALSE' AND LOADED = 'FALSE'" |
ForEach-Object { $_.Delete() }
And you can not remove public and default profiles as they are not profiles actually.
Related
I'm new to scripting any I am trying to make a script that reads PC list from a CSV file and check if a specific process is runnuing.
the following code is:
Function LogWrite
{
Param ([string]$logstring)
Add-content $Logfile -value $($(Get-Date -Format yyyyMMdd-HHmmss) + " - " + $logstring)
}
$LogFile = "Path\to\log.txt" # Location of local log file name
$CsvLocation = "\\path\to\CSV\File\Table.csv" #Location of the CSV file
$csvdata = Import-Csv $ipmCsvLocation
foreach($pc in $csvdata) {
$IcingaProc = "nscp.exe"
$pcname = $pc.Name
Write-Host $("Looking for process "+ $IcingaProc + " in " + $pcname + "...")
$Processes = get-process | Where-Object {$_.ProcessName -Like "nscp*"}
foreach($Proc in $Processes){
if ($Proc.ProcessName -eq $IcingaProc){
Write-Host "Program installed succefully"
LogWrite ("Program installed succefully in "+$pcname)
LogWrite `r`n
}
else{
LogWrite ("Could not find any CINIGA process")
LogWrite `r`n
}
}
}
This is the output I get:
PS User> powershell.exe -ExecutionPolicy Bypass –Noprofile -file "Path\to\script.ps1"
Looking for process nscp.exe in PC1...
Looking for process nscp.exe in PC2...
Looking for process nscp.exe in PC3...
Looking for process nscp.exe in PC4...
it doesn't seems to enter the 2nd foreach loop..
I was indeed pointing to localhost and changed to point to $pcName.
When i "turned" the if command with -ne instead of -eq it worked well!
Thank you for all your help !
Function LogWrite
{
Param ([string]$logstring)
Add-content $Logfile -value $($(Get-Date -Format yyyyMMdd-HHmmss) + " - " + $logstring)
}
$LogFile = "Path\To\LogFIle.txt" # Location of local log file name
$CsvLocation = "\\Path\To\Referance\CSV\Table.csv"
$csvdata = Import-Csv $CsvLocation
foreach($pc in $csvdata) {
$IcingaProc = "nscp"
$pcname = $pc.Name
Write-Host $("Looking for process "+ $IcingaProc + " in " + $pcname + "...")
if (Test-Connection -ComputerName $pcname -Count 1 -Quiet) {
$Processes = get-process -ComputerName $pcname | Where-Object {$_.ProcessName -Like "ns*"}
foreach($Proc in $Processes){
if ($Proc.ProcessName -ne $IcingaProc){
Write-Host ("Could not find any process")
}
else{
Write-Host "Program is installed succefully"
LogWrite ("Program is installed on "+$pcname)
}
}
}
else{
Write-Host ("The PC is not reachable!")
}
}
So I am trying to adapt this code I got from another post for the needs of my current organization. Please see below code:
$Admin = "Administrator","Public","Default","Administrator"
foreach($file in Get-ChildItem C:\Users\)
{
if ($file -in $Admin)
{
Write-Host = "`r`nUser account is" $file ". This is an Administrator Account, it will not be deleted."
}
else
{
Write-Host = "`r`nUser account is" $file ". Checking profiles age..."
$FileDate = (Get-item C:\Users\$file).CreationTime
Write-Host = $FileDate
$TestDate = (Get-Date).addDays(-30)
Write-Host = $TestDate
If ($FileDate -lt $TestDate)
{
Write-Host = "Since" $file "is older than 30 Days (" $FileDate ") it will be deleted."
$UserAccountPath = "C:\\Users\\$file"
$WMIQuery = "SELECT * FROM Win32_UserProfile WHERE localpath = '$UserAccountPath'"
$UserProfile = get-wmiobject win32_userprofile | where localpath -eq c:\\users\\$file
Remove-WmiObject -InputObject "$UserProfile"
}
else
{
Write-Host = "Since File is dated less than 30 days old (" $FileDate ") it will not need to be deleted."
}
}
}
After running this I get the following error:
Remove-WmiObject : Object reference not set to an instance of an object.
At line:28 char:17
+ Remove-WmiObject -InputObject "$UserProfile"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Remove-WmiObject], NullReferenceException
+ FullyQualifiedErrorId : System.NullReferenceException,Microsoft.PowerShell.Commands.RemoveWmiObject
Any help is appreciated.
Basically, the mistake is in this line:
$UserProfile = Get-WmiObject win32_userprofile | Where localpath -EQ c:\\users\\$file
$UserProfile is null, and will always be null, because the equality comparer -eq is looking for an exact match, to put it into perspective:
'C:\some\path' -eq 'C:\\some\\path' # => False
[pscustomobject]#{
localPath = 'C:\some\path'
} | Where-Object localPath -EQ 'C:\\some\\path' # => Null
To fix this, you can do the following:
# $UserAccountPath = "C:\\Users\\$file" // This line is not needed
#
# DirectoryInfo objects have a FullName property for their Absolute Path
$UserProfile = Get-WmiObject win32_userprofile | Where-Object localpath -EQ $file.FullName
Remove-WmiObject -InputObject $UserProfile
$UserProfile = Get-WmiObject win32_userprofile | Where-Object localpath -EQ $file.FullName
$UserProfile.Delete()
I am literally 1 Line away from getting this PS Task completed. Would one of you mind taking a look? This script simply checks the users directory, checks each local users creation date, and deletes it using WMIObject. Everything works up to line 34 (Marked it with ===> in Code block). Error being thrown on my WMI Query. I cannot find out why... Working with WMIExplorer it looks correct.
$Admin = "Administrator"
foreach($file in Get-ChildItem C:\Users\)
{
if ($file -in $Admin)
{
Write-Host = "`r`nUser account is" $file ". This is an Administrator Account, it will not be deleted."
}
else
{
Write-Host = "`r`nUser account is" $file ". Checking profiles age..."
$FileDate = (Get-item C:\Users\$file).CreationTime
Write-Host = $FileDate
$TestDate = (Get-Date).addDays(-30)
Write-Host = $TestDate
If ($FileDate -lt $TestDate)
{
Write-Host = "Since" $file "is older than 30 Days (" $FileDate ") it will be deleted."
$UserAccountPath = "C:\Users\$file"
====> $WMIQuery = "SELECT * FROM Win32_UserProfile WHERE localpath = $UserAccountPath"
$UserProfile = Get-WmiObject -Query $WMIQuery -ComputerName $Computer
Remove-WmiObject -InputObject $UserProfile
}
else
{
Write-Host = "Since File is dated less than 30 days old (" $FileDate ") it will not need to be deleted."
}
}
}
When it is run I get the following Error:
Get-WmiObject : Invalid query "SELECT * FROM Win32_UserProfile WHERE localpath = C:\Users\radconrm"
At C:\Users\AVC00\Documents\PowerShell\Profile Maintenance\TestCommands.ps1:18 char:13
+ $profile = (Get-WmiObject -Query $WMIQuery -ComputerName $Computer)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-WmiObject], ManagementException
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand
Remove-WmiObject : Cannot bind argument to parameter 'InputObject' because it is null.
At C:\Users\AVC00\Documents\PowerShell\Profile Maintenance\TestCommands.ps1:19 char:31
+ Remove-WmiObject -InputObject $profile
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Remove-WmiObject], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RemoveWmiObject
I look forward to your insight! Thank you for your time in advanced!
Double the backslashes. Add quotes to what localpath is equal to. It's like SQL.
$UserAccountPath = "C:\\Users\\$file"
$WMIQuery = "SELECT * FROM Win32_UserProfile WHERE localpath = '$UserAccountPath'"
$UserProfile = Get-WmiObject -Query $WMIQuery -ComputerName $Computer
You may find something like this easier:
get-wmiobject win32_userprofile | where localpath -eq c:\users\$file
I am creating a script which should delete profiles which haven't been used in the last 180 days in Windows systems.
Following is my code.
$profiles = Get-WMIObject -Class Win32_UserProfile | Where {
(!$_.Special) -and
($_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-1))
}
$count = $profiles | Measure-Object | select -ExpandProperty Count
if ($count -eq 0) {
Write-Output "No Profiles found for Deletion"
exit
}
Write-Output "Number of profiles : $count"
$profiledeleted = #()
$profileerror = #()
foreach ($profile in $profiles) {
$profile | Remove-WmiObject
if ($?) {
$profiledeleted += $profile.Localpath
continue
} else {
$profileerror += $profile.Localpath
}
}
if ($profiledeleted.Length -gt 0) {
Write-Output "Localpath of removed profiles"
$profiledeleted
}
if ($profileerror.Length -gt 0) {
Write-Output "Error While removing below profiles"
$profileerror
}
The code should run with the system account but I am getting the following error.
Remove-WmiObject :
At C:\Users\Admin\GRT-2687_deleteunuseduserprofiles.ps1:22 char:32
+ $profile | Remove-WmiObject <<<<
+ CategoryInfo : InvalidOperation: (:) [Remove-WmiObject], COMException
+ FullyQualifiedErrorId : RemoveWMICOMException,Microsoft.PowerShell.Commands.RemoveWmiObject
Edit : It is deleting all the data except the folder C:\Users\Username.
I've got a couple things that i'm working on. One of them is sort of an import/export thing i found on here. but i'm getting the following error
PS C:\Users\joeblogs> C:\Users\joeblogs\Scripts\Copy user data.ps1 Invalid assignment expression. The left hand side of an assignment
operator needs to be something that can be assigned to like a variable
or a property. At C:\Users\delpillay\Documents\Scripts\Copy user
data.ps1:16 char:12
+ $username = <<<< gc env:userame
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : InvalidLeftHandSide
I don't know where to start and i'm not sure what to try...
Below is the code:
$destination = "E:\Users\%username%\Backup"
$folder = "Desktop",
#"Downloads",
"Favorites",
"My Documents",
#"Music",
#"Pictures",
#"Videos",
#"AppData\Local\Mozilla",
#"AppData\Local\Google",
#"AppData\Roaming\Mozilla"
######################################
$username = gc env:userame
$userprofile = gc env:userprofile
##$appData = gc env:localAPPDATA
###### Restore data section ######
if ([IO.Directory]::Exists($destination + "\" + $username + "\"))
{
$caption = "Choose Action";
$message = "A backup folder for $username already exists, would you like to restore the data to the local machine?";
$Yes = new-Object System.Management.Automation.Host.ChoiceDescription "&Yes","Yes";
$No = new-Object System.Management.Automation.Host.ChoiceDescription "&No","No";
$choices = [System.Management.Automation.Host.ChoiceDescription[]]($Yes,$No);
$answer = $host.ui.PromptForChoice($caption,$message,$choices,0)
if ($answer -eq 0)
{
write-host -ForegroundColor green "Restoring data to local machine for $username"
foreach ($f in $folder)
{
$currentLocalFolder = $userprofile + "\" + $f
$currentRemoteFolder = $destination + "\" + $username + "\" + $f
write-host -ForegroundColor cyan " $f..."
Copy-Item -ErrorAction silentlyContinue -recurse $currentRemoteFolder $userprofile
if ($f -eq "AppData\Local\Mozilla") { rename-item $currentLocalFolder "$currentLocalFolder.old" }
if ($f -eq "AppData\Roaming\Mozilla") { rename-item $currentLocalFolder "$currentLocalFolder.old" }
if ($f -eq "AppData\Local\Google") { rename-item $currentLocalFolder "$currentLocalFolder.old" }
}
rename-item "$destination\$username" "$destination\$username.restored"
write-host -ForegroundColor green "Restore Complete!"
}
else
{
write-host -ForegroundColor yellow "Aborting process"
exit
}
}
###### Backup Data section ########
#else
{
Write-Host -ForegroundColor green "Outlook is about to close, save any unsaved emails then press any key to continue ..."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Get-Process | Where { $_.Name -Eq "OUTLOOK" } | Kill
write-host -ForegroundColor green "Backing up data from local machine for $username"
foreach ($f in $folder)
{
$currentLocalFolder = $userprofile + "\" + $f
$currentRemoteFolder = $destination + "\" + $username + "\" + $f
$currentFolderSize = (Get-ChildItem -ErrorAction silentlyContinue $currentLocalFolder -Recurse -Force | Measure-Object -ErrorAction silentlyContinue -Property Length -Sum ).Sum / 1MB
$currentFolderSizeRounded = [System.Math]::Round($currentFolderSize)
write-host -ForegroundColor cyan " $f... ($currentFolderSizeRounded MB)"
Copy-Item -ErrorAction silentlyContinue -recurse $currentLocalFolder $currentRemoteFolder
}
$oldStylePST = [IO.Directory]::GetFiles($appData + "\Microsoft\Outlook", "*.pst")
foreach($pst in $oldStylePST)
{
if ((test-path -path ($destination + "\" + $username + "\Documents\Outlook Files\oldstyle")) -eq 0){new-item -type directory -path ($destination + "\" + $username + "\Documents\Outlook Files\oldstyle") | out-null}
write-host -ForegroundColor yellow " $pst..."
Copy-Item $pst ($destination + "\" + $username + "\Documents\Outlook Files\oldstyle")
}
write-host -ForegroundColor green "Backup complete!"
}
Few observations:
You are not commenting the Favourites and My Documents. If you want to use them then use comma separated directly.
Use this:
$destination = "E:\Users\%username%\Backup"
$folder = "Desktop","Favorites","My Documents"
#"Downloads",
#"Favorites",
#"My Documents",
#"Music",
#"Pictures",
#"Videos",
#"AppData\Local\Mozilla",
#"AppData\Local\Google",
#"AppData\Roaming\Mozilla"
You have missed the n in username:
$username = gc env:username
Donot use gc env:username. Instead directly access them like this below: Completely reframed:
$destination = "E:\Users\%username%\Backup"
$folder = "Desktop","Favorites","My Documents"
#"Downloads",
#"Favorites",
#"My Documents",
#"Music",
#"Pictures",
#"Videos",
#"AppData\Local\Mozilla",
#"AppData\Local\Google",
#"AppData\Roaming\Mozilla"
######################################
$username = $env:username
$userprofile = $env:userprofile
##$appData = gc env:localAPPDATA
These are the major things that have been fixed. Hope it helps you.