I have to code a script, which deploys two different registry keys remotely to all clients in our Active Directory. The script doesnt respond with any errors, but it still seems, that the keys aren't getting created. Can you maybe help me?
Im not used to programming so please keep that in mind :D
$pc = Get-ADComputer -filter {name -like "WS226"}
foreach ($object in $pc)
{
$object.name
#New Powershell-Remotesession with $PC
$session = New-PSSession -Computername $object.name
$Dir ="HKLM:\SOFTWARE\ORACLE\KEY_OraClient11g_home1"
If (Test-Path $Dir)
{
New-Item -Path HKLM:\SOFTWARE\ORACLE\KEY_OraClient11g_home1 -Name NewKey -Value "Default Value" -Force
New-ItemProperty -Path HKLM:\SOFTWARE\ORACLE\KEY_OraClient11g_home1\NewKey -Name "NLS_DATE_FORMAT" -PropertyType "String" -Value "DD.MM.RRRR"
}
else
{
ECHO "key"
}
$Dir ="HKLM:\SOFTWARE\ORACLE\KEY_OraClient11g_home1"
If (Test-Path $Dir)
{
New-Item -Path HKLM:\SOFTWARE\ORACLE\KEY_OraClient11g_home1 -Name NewKey2 -Value "Default Value" -Force
New-ItemProperty -Path HKLM:\SOFTWARE\ORACLE\KEY_OraClient11g_home1\NewKey2 -Name " NLS_NUMERIC_CHARACTERS" -PropertyType "String" -Value ".,"
}
else
{
ECHO "key"
}
}
You are creating the pssession but you don't use it.
Put your code in a invoke-command.
Example
Invoke-command -Session $Session -scriptblock{
$Dir ="HKLM:\SOFTWARE\ORACLE\KEY_OraClient11g_home1"
If (Test-Path $Dir)
{
New-Item -Path HKLM:\SOFTWARE\ORACLE\KEY_OraClient11g_home1 -Name NewKey -
Value "Default Value" -Force
#your other code goes here
}
Related
i have trouble with "New-PSDrive -Root"
When i try to map a New-PSDrive -Root $patch with a $path using an array, the cmd does not map the drive but give me an error : "The network Path was not found".
The path is working if i use an explorer in my windows.
How can i fix that ?
Thanks a lot
exemple :
foreach ($s in $serverlist)
{
$path = "\\$s\e$\Updates\file\
New-PSDrive -Name "S" -Root $path -Persist -PSProvider "FileSystem" -Credential $cred
}
Problem
This is the entire script :
Get-Date -Format "dddd MM/dd/yyyy HH:mm K">> "C:\file\results.txt"
$cred = Get-Credential -Credential domain\name
$serverlist = #(get-content -Path "C:\file\serverlist.txt")
foreach ($s in $serverlist)
{
$path = "\\$s\e$\Updates\file\"
New-PSDrive -Name "S" -Root $path -Persist -PSProvider "FileSystem" -Credential $cred
$path2 = "\\$s\e$\Updates\file\errors.txt"
$file = Get-Content $path2
$containsWord = $file | %{$_ -match "0"}
if ($containsWord -contains $true) {
Out-File -FilePath "C:\file\results.txt" -Append -InputObject "$s : ok"
} else {
Out-File -FilePath "C:\file\results.txt" -Append -InputObject "$s : nok"
}
Remove-PSDrive -Name "S"
}
EDIT 1 : If i try to access to the file directly by an windows explorer with the same credential and I, after that, run the script, it works
As commented, the user in $cred may have permissions to access the file in the path on the server, but you as it seems do not.
Try using Invoke-Command where you can execute a scriptblock using different credentials than your own:
$cred = Get-Credential -Credential domain\name
$serverlist = Get-Content -Path "C:\file\serverlist.txt"
# loop through the list of servers and have these perform the action in the scriptblock
$result = foreach ($s in $serverlist) {
Invoke-Command -ComputerName $s -Credential $cred -ScriptBlock {
# you're running this on the server itself, so now use the LOCAL path
$msg = if ((Get-Content 'E:\Updates\file\errors.txt' -Raw) -match '0') { 'ok' } else { 'nok' }
# output 'ok' or 'nok'
'{0} : {1}' -f $env:COMPUTERNAME, $msg
}
}
# write to the results.txt file
# change 'Add-Content' in the next line to 'Set-Content' if you want to create a new, blank file
Get-Date -Format "dddd MM/dd/yyyy HH:mm K" | Add-Content -Path 'C:\file\results.txt'
$result | Add-Content -Path 'C:\file\results.txt'
In fact, you don't even need a foreach loop because parameter -ComputerName can receive an array of server names:
$result = Invoke-Command -ComputerName $serverlist -Credential $cred -ScriptBlock {
# you're running this on the server itself, so now use the LOCAL path
$msg = if ((Get-Content 'E:\Updates\file\errors.txt' -Raw) -match '0') { 'ok' } else { 'nok' }
# output 'ok' or 'nok'
'{0} : {1}' -f $env:COMPUTERNAME, $msg
}
I have the following PowerShell script that creates a session with Windows server administrator account.I want to report in case of failure of Invoke-command the error and save it in a file
Below is the code that I wrote but if i tamper for example .json file(set a wrong username),execution fails and error_report.txt is not created
#Param(
$user = "lamda"
#)
$user_domain = (Get-WmiObject Win32_ComputerSystem).Domain
$user_computer = (Get-WmiObject Win32_ComputerSystem).Name
$file = "error_report.txt"
If ((Test-Path "creds.json") -eq $True)
{
$jsonfile = Get-ChildItem creds.json
if ($jsonfile.Length -eq 0)
{
#$file = "error_report.txt"
Set-Content -Path $file -Value "Error:The file 'creds.json' is empty"
break
}
else
{
$creds= (Get-Content creds.json | Out-String | ConvertFrom-Json)
$admin = $creds.username
$passwd = $creds.password
if (($admin) -and ($passwd))
{
$Password = ConvertTo-SecureString -String $passwd -AsPlainText -Force
$credential = [pscredential]::new($admin,$Password)
$command = Invoke-Command -ComputerName Server.$user_domain -FilePath
C:\SECnology\Data\Utilities\Updating.ps1 -ArgumentList
$user,$admin,$user_computer -Credential $credential
If ($command -eq $false)
{
$file = "error_report.txt"
Set-Content -Path $file -Value "Error:Session between user and server
could not be created,please check your Credentials"
}
break
}
elseif (([string]::IsNullOrEmpty($admin)) -or ([string
]::IsNullOrEmpty($passwd)))
{
#$file = "error_report.txt"
Set-Content -Path $file -Value "Error:One object of 'creds.json' seems
to be empty.Please check your file "
}
}
break
}
else
{
#$file = "error_report.txt"
Set-Content -Path $file -Value "Error:The file 'creds.json' does not exist"
}
I think the issue is the way you are defining the condition on your if statement.
You use -eq $false however if you connections fails it does not set the vale of command to $false it will leave command as a null as it return no value (it errorred).
What you can try is either use the null operator (!) in your if statement so:
If (!$command){Do stuff}
Or you can give you invoke command an error variable and check if that has a value when run.
$command = Invoke-Command -ComputerName Server.$user_domain -FilePath
C:\SECnology\Data\Utilities\Updating.ps1 -ArgumentList
$user,$admin,$user_computer -Credential $credential -ErrorVariable TheError
If ($TheError)
{Do stuff}
This script makes changes to all users' profiles.
Here is the script:
# Get each user profile SID and Path to the profile
$UserProfiles = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*" |
Where {$_.PSChildName -match "S-1-5-21-(\d+-?){4}$" } |
Select-Object #{Name="SID"; Expression={$_.PSChildName}}, #{Name="UserHive";Expression={"$($_.ProfileImagePath)\NTuser.dat"}}
# Loop through each profile on the machine
foreach ($UserProfile in $UserProfiles) {
# Load User ntuser.dat if it's not already loaded
if (($ProfileWasLoaded = Test-Path Registry::HKEY_USERS\$($UserProfile.SID)) -eq $false) {
Start-Process -FilePath "CMD.EXE" -ArgumentList "/C REG.EXE LOAD HKU\$($UserProfile.SID) $($UserProfile.UserHive)" -Wait -WindowStyle Hidden
}
}
# Manipulate the registry
$key = "Registry::HKEY_USERS\$($UserProfile.SID)\Software\SomeArchaicSoftware\Configuration"
New-Item -Path $key -Force | Out-Null
New-ItemProperty -Path $key -Name "LoginURL" -Value "https://www.myCompany.local" -PropertyType String -Force | Out-Null
New-ItemProperty -Path $key -Name "DisplayWelcome" -Value 0x00000001 -PropertyType DWORD -Force | Out-Null
$key = "$key\UserInfo"
New-Item -Path $key -Force | Out-Null
New-ItemProperty -Path $key -Name "LoginName" -Value "$($ENV:USERDOMAIN)\$($ENV:USERNAME)" -PropertyType STRING -Force | Out-Null
# Unload NTuser.dat
if ($ProfileWasLoaded -eq $false) {
[GC]::Collect()
Start-Sleep 1
Start-Process -FilePath "CMD.EXE" -ArgumentList "/C REG.EXE UNLOAD HKU\$($UserProfile.SID)" -Wait -WindowStyle Hidden| Out-Null
}
I only need changes to the current logged on user HKEY_USERS hive.
Can anyone help me change the script so it's only the current logged in user who gets the changes?
You can determine the SID of a currently logged-in user via WMI. Check for the owner of a running explorer.exe process, then resolve the account name to its SID:
$user = (Get-WmiObject Win32_Process -Filter "Name='explorer.exe'").GetOwner()
$fltr = "Name='{0}' AND Domain='{1}'" -f $user.User, $user.Domain
$sid = (Get-WmiObject Win32_UserAccount -Filter $fltr).SID
Still, I think a logon script would be a better place for changes to a user's registry settings.
I am working on this command to be able to view and edit a registry key remotely to a computer on a joined domain when I need to test something. In this case, I am looking at Excel's "vbawarninsg" key. This works just fine.
cls
$computername = Read-Host "Enter computer name..."
Invoke-Command -ComputerName $computername {Get-ItemProperty -Path 'REGISTRY::HKEY_USERS\xxxxxxx\Software\Policies\Microsoft\office\16.0\excel\security' } |
Select-Object PSComputerName, vbawarnings, PSParentPath | fl
$name = "vbawarnings"
The next part is to set a new value for the "vbawarnings" key using New-ItemProperty. When I assigned a variable for the -Path name it gives me an error "Cannot bind argument to parameter 'Path' because it is null."
This is the script that gives me an error
cls
$computername = Read-Host "Enter computer name..."
$registryPath = 'REGISTRY::HKEY_USERS\xxxxxxx\Software\Policies\Microsoft\office\16.0\excel\security'
Invoke-Command -ComputerName $computername {Get-ItemProperty -Path $registryPath } |
Select-Object PSComputerName, vbawarnings, PSParentPath | fl
$name = "vbawarnings"
$value = Read-Host "To modify...Enter a value"
New-ItemProperty -Path $registryPath -Name $name -Value $value `
-PropertyType DWORD -Force -Verbose | Out-Null
Any help is greatly appreciated!
In order to use a variable remotely (such as the case with Invoke-Command), you need to use the $using: variable scope:
Invoke-Command -ComputerName $cn {
Get-ItemProperty -Path $using:regPath
}
or pass it as a parameter:
Invoke-Command -ComputerName $cn {
param($path)
Get-ItemProperty -Path $path
} -ArgumentList '-path', $regPath
See this article
When you do Invoke-Command, that scriptblock gets sent to the remote server.
Invoke-Command -ComputerName $computername {Get-ItemProperty -Path $registryPath }
On the remote server, $registryPath is null even though you have it locally in your script.
So just hardcode the registry path instead:
Invoke-Command -ComputerName $computername {Get-ItemProperty -Path 'REGISTRY::HKEY_USERS\xxxxxxx\Software\Policies\Microsoft\office\16.0\excel\security' }
I'm required to run a TPM command (requires admin access).
Lets use these for the legend:
Angelo - Standard user
AngeloAdmin - Admin user
Windows7 - Computer that has a standard user in it
How can I use my standard account to run the script as an Administrator to execute a script to another computer with a standard account remotely?
Heres the partial code I will run:
Set-Variable -Name BuildLog -Scope Global -Force
Set-Variable -Name Errors -Value $null -Scope Global -Force
Set-Variable -Name LogFile -Scope Global -Force
Set-Variable -Name Phase -Scope Global -Force
Set-Variable -Name RelativePath -Scope Global -Force
Set-Variable -Name Sequence -Scope Global -Force
Set-Variable -Name Title -Scope Global -Force
Function ConsoleTitle ($Title){
$host.ui.RawUI.WindowTitle = $Title
}
Function DeclareGlobalVariables {
$Global:BuildLog = $Env:windir+"\Logs\BuildLogs\Build.csv"
$Global:LogFile = $Env:windir+"\Logs\BuildLogs\TPM_On.log"
$Global:Phase = "Final Build"
$Global:Sequence = ""
$Global:Title = "TPM Clear Ownership"
}
Function GetRelativePath {
$Global:RelativePath = (split-path $SCRIPT:MyInvocation.MyCommand.Path -parent)+"\"
}
Function ClearTPM {
#Declare Local Memory
Set-Variable -Name ClassName -Value "Win32_Tpm" -Scope Local -Force
Set-Variable -Name Computer -Value $env:COMPUTERNAME -Scope Local -Force
Set-Variable -Name NameSpace -Value "ROOT\CIMV2\Security\MicrosoftTpm" -Scope Local -Force
Set-Variable -Name oTPM -Scope Local -Force
$oTPM = Get-WmiObject -Class $ClassName -ComputerName $Computer -Namespace $NameSpace
$Output = "Clearing TPM Ownership....."
Write-Host "Clearing TPM Ownership....." -NoNewline
$Temp = $oTPM.SetPhysicalPresenceRequest(5)
If ($Temp.ReturnValue -eq 0) {
$Output = "Success"
Write-Host "Success" -ForegroundColor Yellow
} else {
$Output = "Failure"
Write-Host "Failure" -ForegroundColor Red
$Global:Errors++
}
Out-File -FilePath $Global:LogFile -InputObject $Output -Append -Force
#Cleanup Local Memory
Remove-Variable -Name oTPM -Scope Local -Force
}
Function ProcessLogFile {
If ((Test-Path $Env:windir"\Logs") -eq $false) {
New-Item -ItemType Directory -Path $Env:windir"\Logs"
}
If ((Test-Path $Env:windir"\Logs\ApplicationLogs") -eq $false) {
New-Item -ItemType Directory -Path $Env:windir"\Logs\ApplicationLogs"
}
If ((Test-Path $Env:windir"\Logs\BuildLogs") -eq $false) {
New-Item -ItemType Directory -Path $Env:windir"\Logs\BuildLogs"
}
If ($Global:Errors -eq $null) {
If (Test-Path $Global:LogFile) {
Remove-Item $Global:LogFile -Force
}
$File1 = $Global:LogFile.Split(".")
$Filename1 = $File1[0]+"_ERROR"+"."+$File1[1]
If (Test-Path $Filename1) {
Remove-Item $Filename1 -Force
}
$Global:Errors = 0
} elseIf ($Global:Errors -ne 0) {
If (Test-Path $Global:LogFile) {
$Global:LogFile.ToString()
$File1 = $Global:LogFile.Split(".")
$Filename1 = $File1[0]+"_ERROR"+"."+$File1[1]
Rename-Item $Global:LogFile -NewName $Filename1 -Force
}
} else {
$date = get-date
$LogTitle = $Global:Phase+[char]9+$Global:Sequence+[char]9+$Global:Title+[char]9+$date.month+"/"+$date.day+"/"+$date.year+" "+$date.hour+":"+$date.minute
Out-File -FilePath $Global:BuildLog -InputObject $LogTitle -Append -Force
}
}
Function ExitPowerShell {
If (($Global:Errors -ne $null) -and ($Global:Errors -ne 0)) {
Exit 1
}
}
cls
GetRelativePath
DeclareGlobalVariables
ConsoleTitle $Global:Title
ProcessLogFile
ClearTPM
ProcessLogFile
Start-Sleep -Seconds 5
ExitPowerShell
If you want to run the script as a different user you can 'SHIFT+Right click > Run as a different user' but that works only on applications, so you have to run Powershell as a different user and then the script, you can make a batch file to do that. Here is an example of what you will need in the batch file.
runas /user:yourdomain.com\administrator powershell
If you dont have a domain use the computer name
runas /noprofile /user:computername\administrator powershell