I need your help
I need to print an logic condition in the specifc PowerShell output command.
Get-ItemProperty -Path 'HKLM:SOFTWARE\Policies\Microsoft\WindowsNT\TerminalServices' -Name fDisableCdm | Select fDisableCdm
I wrote a little script for test, but in my script I made a own conditional output. But I want print that what value have inside registry key and not print an own condition.
My script
if ($process=Get-ItemProperty -Path 'HKLM:SOFTWARE\Policies\Microsoft\WindowsNT\TerminalServices' -Name fDisableCdm -ErrorAction SilentlyContinue) {write-host "1"} else {write-host "0"}
You can help me ?
I waiting for help and tanks for all !
$regKey = "HKLM:SOFTWARE\Policies\Microsoft\WindowsNT\Terminal Services"
$regValue = 'fDisableCdm'
Try {
$process=Get-ItemProperty -Path $regKey -Name $regValue -ErrorAction Stop
Write-Output (-join($regValue,": ",$process.$regValue))
}
Catch {
Write-Output "There was an error: $($PSItem.ToString())"
}
You will need to check to see if your registry key for Terminal Services has a space or not. Mine has a space.
Otherwise, this script allows you to set the two variables at the beginning of the script, performs the requested lookup and, if no error occurs, outputs the requested information.
In the event of an error, the script outputs an appropriate error message.
Reference for meaningful error handling:
https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-exceptions?view=powershell-7.1
Related
Firstly I do apologise if this isn't the correct forum to be posting this question and if this isn't the place to be asking can anyone direct me to a new person forum?
Secondly you'll soon discover that I really don't know much about PowerShell or Visual Studio but I'm learning... I'm sure the Powershell script your going to see could be better but it works.
So my issue was with a system that output .txt files onto 2 PC's LH & RH these .txt files were output with different names as it was using 3 different products.
We then needed these files to be filtered by product and copied to a network drives while also being archived and deleted from the original folder.. Oh and this needed to be done real time.
So my Powershell script I've been using is the following
$folder = 'Target Folder'
$timeout = 1000
$filesystemwatcher = new-object system.IO.filesystemwatcher $folder
write-host "Monitoring... $folder
Transfering..."
while ($true) {
$result = $FileSystemWatcher.WaitForChanged('all', $timeout)
if ($result.timeout -eq $false)
{
write-warning ('file {0} : {1}' -f $result.changetype, $result.name)
}
$targetdirectory = "Target folder"
$sourcedirectory = "export folder"
if (-not(Test-Path -path $targetdirectory)) {
New-Item $targetdirectory -Type Directory}
Copy-Item -Path $sourcedirectory\"*.txt" -Destination $targetdirectory
$Files = Get-ChildItem -Path export folder -Filter "*.txt" -Recurse
foreach($File in $Files)
{
if ($File.name -like "1*.txt")
{
Move-Item -Path $File.FullName "1 folder"
}
elseif ($File.name -like "2*.txt")
{
Move-Item -Path $File.FullName "2 folder"
}
elseif ($File.name -like "3*.txt")
{
Move-Item -Path $File.FullName "3 folder"
}
}
}
}
Now this script gets the files moved and works but its a Powershell script and its running 24/7 365 days a year sometimes the script had stopped sometimes the script has been messed with its just not reliable enough.
So I want to turn it into a application via Visual Studio.
Is it possible? remember i have never used Visual Studio before (Been trying it for a few hours learnt some basics)
Has anyone done anything similar to this before/ is there any guide anyone can think of that would suit my needs more?
I'm looking for the application to have the following
A status screen ie what files it has found and where it has moved them to
A setting option to be able to set.. amount of filter string/save paths... change source & export/archive paths etc
Can anyone point me in the right direction? Being new I don't know what to search for to get guides on my needs
Cheers
For license porpuses I try to automate the counting process instead of having to login into every single server, go into directory, search a file name and count the results based on the change date.
Want I'm aiming for:
Running a powershell script every month that checks the directory "C:\Users" for the file "Outlook.pst" recursively. And then filters the result by change date (one month or newer). Then packing this into an email to send to my inbox.
I'm not sure if that's possible, cause I am fairly new to powershell. Would appreciate your help!
It is possible.
I dont know how to start a ps session on a remote computer, but I think the cmdlet Enter-PSSession will do the trick. Or at least it was the first result while searching for "open remote powershell session". If that does not work use the Invoke-Command as suggested by lit to get $outlookFiles as suggested below.
For the rest use this.
$outlookFiles = Get-ChildItem -Path "C:\Users" -Recurse | Where-Object { $_.Name -eq "Outlook.pst" }
Now you have all files that have this name. If you are not familiar with the pipe in powershell it redirects all objects it found with the Get-ChildItem to the next pipe section and here the Where-Object will filter the received objects. If the current object ($_) will pass the condition it is returned by the whole command.
Now you can filter these objects again to only include the latest ones with.
$latestDate = (Get-Date).AddMonths(-1)
$newFiles = $outlookFiles | Where-Object { $_.LastAccessTime -gt $latestDate }
Now you have all the data you want in one object. Now you only have to format this how you like it e.g. you could use $mailBody = $newFiles | Out-String and then use Send-MailMessage -To x#y.z -From r#g.b -Body $mailBodyto send the mail.
I am currently implementing a "remove settings" for all users in a Windows uninstaller and came over an issue I am not even sure is possible to solve.
The application stores credential entries for the current user using the CredentialManager (keymgr.dll). Let's call the target of the credential "X". On uninstall all credentials with stored with target "X" should be removed on all users. The uninstaller of course requires administrator privileges but still I find it very difficult to accomplish this.
For the current user that command is generally solved via cmdkey /delete=:X from a command prompt. As far as I know cmdkey.exe /list only helps to list entries for the current user and can't remove local entries from another user.
I have learned that the credentials are stored as OS files under the C:\Users\_user_\AppData\Local\Microsoft\Credentials folder, but I can't know which files are the entries I want to delete and removing all would be dangerous for other applications. Also I assume removing OS files will be dangerous and could have limitations (extra UAC prompt?) as well.
Runas command is the closest shot I got but because it requires the password of the user it becomes very difficult and not something I would want in the uninstaller. I also would need a way to get the username and domain for each user and iterate them.
I would prefer to use either cmd or powershell for this.
Don't want to necro an old post but I needed to do this myself so I figured I'd add this in case anyone else needs it:
cmdkey /list | ForEach-Object{if($_ -like "*Target:*" -and $_ -like "*microsoft*"){cmdkey /del:($_ -replace " ","" -replace "Target:","")}}
Powershell one liner that will remove any credentials with Microsoft in the string.
Reference:
https://gist.github.com/janikvonrotz/7819990
I ran this and it purged it locally without needing to run as admin (but I am a local admin)
The cmdkey.exe utility when run from a batch file or a PowerShell command may encounter two issues related to special characters.
1. If run from a batch file, if the credential has "(" or ")" without the double quotes, that is left and right paren, that credential will not be removed.
2. If the credential name aka targetname, has a hyphen surronded by spaces the cmdkey will not remove or create a a credential with that string " - ".
There are a few powershell modules written to try and do this, but the only one i found that handles this exceptions was on Github
https://github.com/bamcisnetworks/BAMCIS.CredentialManager
BAMCIS.CredentialManager
Using this i was able to create credentials to set up a test environment with parens or hyphens, but more importantly to remove them by gathering the users list of cached credentials using the modules command and then passing the information in the command to the remove command to remove ALL cached credentials.
One caveat. After removing the command, after some period of time two cached credentials dynamically reappear.
So to address frequent user lock out issues i am going to try and deploy this using SCCM under user context at logoff. Otherwise a system restart after removing the credentials may be needed.
Here is a prototype script that imports the module and then uses it to remove all cached credentials, As always, test, test, test and use at your own risk!
Clear-host
import-Module "$PSScriptRoot\BAMCIS.CredentialManager\BAMCIS.CredentialManager.psd1"
$L = Get-CredManCredentialList -ErrorAction SilentlyContinue
If($L -eq $null)
{
Write-host "No Cached Credentials found to remove, no action taken"
$LASTEXITCODE = 0
Write-host "The last exit code is $LASTEXITCODE"
}
Else
{
ForEach($cred in $L)
{
Write-host "`tProcessing...`n"
Write-host "$($cred.TargetName.ToString())`n"
Write-host "$($cred.Type.ToString())`n`n"
$R = Remove-CredManCredential -TargetName $($cred.TargetName.ToString()) -Type $($cred.Type.ToString()) -Force
}
$L = Get-CredManCredentialList -ErrorAction SilentlyContinue -ErrorVariable $Cred_Error
If($L -eq $null)
{
Write-host "All Cached Credentials removed, program Complete"
$LASTEXITCODE = 0
Write-host "The last exit code is $LASTEXITCODE"
}
Else
{
Write-host "WARNING: One or more Cached Credentials were not removed, program Complete"
$LASTEXITCODE = 1
}
}
Batch, elevated cmd prompt:
To find the main ones, lists any with MS.O, Micro and teams:
for /f "tokens=1-4 Delims=:=" %A in ('cmdkey /list ^| findstr Target: ^| findstr /i "MS.O Micro Teams"') do #echo %D
This deletes all the entries for teams:
for /f "tokens=1-4 Delims=:=" %A in ('cmdkey /list ^| findstr /i teams') do #cmdkey /delete:%D
If you want to include this as a script the syntax will be slightly different. Double the %%A %%D vars
Ran into similar issue, clearing old credentials for non domain joined devices. Created logon task to clear credentials. In my case was looking for particular file server, so not to clear all creds by accident. Because of syntax issue when piping string expressions into task, was easier to create reference .ps1 then reference in task. Pushed this script through Intune....
# Full path of the file
$file = 'C:\script\clearcreds.ps1'
#If the file does not exist, create it.
if (-not(Test-Path -Path $file -PathType Leaf)) {
try {
$null = New-Item -Path "C:\ProgramData\CentraStage\Packages" -Name
"clearcreds.ps1" -ItemType "file" -Value 'cmdkey /list | ForEach-Object{if($_ -
like "*Target:*" -and $_ -like "*fileserver*"){cmdkey /del:($_ -replace " ","" -replace "Target:","")}}'
Write-Host "The file [$file] has been created."
}
catch {
throw $_.Exception.Message
}
}
#######################################
#Create ScheduledTask to Run at log on.
#######################################
$schtaskName = "Clear Cached Creds "
$schtaskDescription = "Clears Cached Creds for each user at logon."
$trigger = New-ScheduledTaskTrigger -AtLogOn
$class = cimclass MSFT_TaskEventTrigger root/Microsoft/Windows/TaskScheduler
#Execute task in users context
$principal = New-ScheduledTaskPrincipal -GroupId "S-1-5-32-545" -Id "Author"
$action3 = New-ScheduledTaskAction -Execute 'Powershell.exe' "-File C:\script\clearcreds.ps1"
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries
$null=Register-ScheduledTask -TaskName $schtaskName -Trigger $trigger -Action $action3 -Principal $principal -Settings $settings -Description
$schtaskDescription -Force
Start-ScheduledTask -TaskName $schtaskName
Goal:
To edit a specific registry key setting for a specific user, and no others, in powershell.
Known:
OS: Windows 8.1 Embedded Industry Pro (Same as Win 8.1, but with some embedded features)
I can do this manually on the target machine by opening REGEDIT, selecting HKU, then click on File Menu, click on Load Hive, navigate to the user's profile directory, e.g: c:\users\MrEd and when prompted, type in 'ntuser.dat' - import HKEY_CURRENT_USER. The Hive will be loaded into HKU where you can navigate and make necessary modifications.
Summary:
I have a powershell script that returns the SID of the specific user, but when used in context of the registry hive, the hive"is not found" -- so I'm guessing I must be missing a step? How does one "Load Hive" from Powershell? Or am I missing a special, magical, goats-entrails-on-keyboard incantation somewhere?
Param(
[string]$user= $null
)
Function GetSIDfromAcctName()
{
Param(
[Parameter(mandatory=$true)]$userName
)
$myacct = Get-WmiObject Win32_UserAccount -filter "Name='$userName'"
return $myacct.sid
}
if($user)
{
$sid = GetSIDfromAcctName $user
New-PSDrive HKU Registry HKEY_USERS
$myHiveEntry = Get-Item "HKU:\${sid}"
Write-Host "Key:[$myHiveEntry]"
}
Your existing code should work for a user whose hive is already loaded (like a currently logged in user), but it makes no attempt to load the hive.
I don't know of a way to make a programmatic call to load a hive, but you can shell out to reg.exe.
This ends up being kind of janky. It seems to have issues unloading the hive if it's in use anywhere, so I've put a bunch of crap in place in this sample to try to get rid of stuff that might be holding it open, but in my tests, it can take quite a while before the reg unload command is successful, hence the whole retry portion in the finally block.
This is super unpolished, I just whipped it up on the spot.
Function GetSIDfromAcctName()
{
Param(
[Parameter(mandatory=$true)]$userName
)
$myacct = Get-WmiObject Win32_UserAccount -filter "Name='$userName'"
return $myacct.sid
}
$user = 'someuser'
$sid = GetSIDfromAcctName -userName $user
$path = Resolve-Path "$env:USERPROFILE\..\$user\NTUSER.DAT"
try {
reg load "HKU\$sid" $path
#New-PSDrive -Name HKUser -PSProvider Registry -Root "HKEY_USERS\$sid"
#Get-ChildItem HKUser:\
Get-ChildItem Registry::\HKEY_USERS\$sid
} finally {
#Remove-PSDrive -Name HKUser
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
$retryCount = 0
$retryLimit = 20
$retryTime = 1 #seconds
reg unload "HKU\$sid" #> $null
while ($LASTEXITCODE -ne 0 -and $retryCount -lt $retryLimit) {
Write-Verbose "Error unloading 'HKU\$sid', waiting and trying again." -Verbose
Start-Sleep -Seconds $retryTime
$retryCount++
reg unload "HKU\$sid"
}
}
This doesn't use a PS drive, but that code is in there too, commented out.
Note that if you don't name the hive mount point with the SID, you won't actually need the SID at all because you use the username to find the NTUSER.DAT file anyway.
Is it a way to detect if there is any file added in a folder? Include the sub-folder.
For example, check if any text file *.txt is added in folder c:\data-files\ or its sub-folders.
The folder can be shared folder of another machine too.
Perhaps you are confused on the types of events that are triggered:
http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher_events(v=vs.110).aspx
This should work, taken from the link above and modified for your requirements:
#By BigTeddy 05 September 2011
#This script uses the .NET FileSystemWatcher class to monitor file events in folder(s).
#The advantage of this method over using WMI eventing is that this can monitor sub-folders.
#The -Action parameter can contain any valid Powershell commands. I have just included two for example.
#The script can be set to a wildcard filter, and IncludeSubdirectories can be changed to $true.
#You need not subscribe to all three types of event. All three are shown for example.
# Version 1.1
$folder = '\\remote\shared' # Enter the root path you want to monitor.
$filter = '*.txt' # You can enter a wildcard filter here.
# In the following line, you can change 'IncludeSubdirectories to $true if required.
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property #{IncludeSubdirectories = $true;NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'}
# Here, all three events are registerd. You need only subscribe to events that you need:
Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "The file '$name' was $changeType at $timeStamp" -fore green
Out-File -FilePath c:\scripts\filechange\outlog.txt -Append -InputObject "The file '$name' was $changeType at $timeStamp"}
Please note that once you close the powershell console the fileSystemWatcher is thrown away, and will no longer monitor the folder(s). So you have to make sure the powershell window stays open. In order to do that without it getting in your way I suggest a scheduled task http://blogs.technet.com/b/heyscriptingguy/archive/2011/01/12/use-scheduled-tasks-to-run-powershell-commands-on-windows.aspx