Cannot run PS1 with different credential - powershell

I have a script, which does multiple things on different servers. If I log on to a computer with my admin account, the script runs fine. However, I want to to be able to run it on my standard account by using my admin credential.
I have used invoke-command with -credential or get-credential at the beginning of my script but none has worked. I keep getting "access is denied"
Here is a part of my script.
$Computername = "Computer"
if (test-Connection -ComputerName $ComputerName -Count 1 -quiet) {Write-Host "`n$computername is ONLINE."}
else {Write-Host "`n$computername is OFFLINE."
Get-ADComputer -identity $computername
if (!$?) {Write-Host "`n$computername is not found in ActiveDir."}
Else {
$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$root = $dom.GetDirectoryEntry()
$search = [System.DirectoryServices.DirectorySearcher]$root
$search.filter = "(&(objectclass=computer)(name=$computername))"
$search.findall() | %{$_.GetDirectoryEntry() } | %{$_.DeleteObject(0)}
Write-Host "`n$computername is deleted from ActiveDir."
}}

Related

How do I remote into multiple remote computers via PS to discover one specific app and determine the version number on each remote device? No output

FYI: I'm very new to PS and I'm using this as a learning opportunity. Again, I'm trying to find a
specific application on a list of multiple remote devices and determine the version number of the
application on their corresponding host system. I attempted this via a registry query (found this to
be challenging) and then I used Get-WMIObject. As of now, I'm working with this as my script. It's
not producing any output; instead, it returns to the command prompt with no errors or messages.
Script to find specific application and version in multiple remote devices:
$Servers = Get-Content -Path C:\\files\Serverlist.txt
$CIMSession = New-CIMSession -ComputerName $Servers Get-Credentials
$Vendor = "App Name"
foreach($Serv in $Servers) {
If(Test-Connection -ComputerName $Serv -Count 1 -Quiet) {
$Status = Get-Ciminstance Win32_Product -Computername $Serv | Where-object {$_.Version -contains
$Vendor}
if($Status) {
Out-file -Filepath C:\\files\AppVerResults.txt
}
}
}
I also tried adjusting the following section of the script as shown below but it presented me with the error "Get-CimInstance : Access is denied." Is this error message due to group policy or so? I am able to remote into the device corresponding to the message via RDP.
if($Status) {
$Servers + " - "
$Status | Out-file -Filepath C:\\files\AppVerResults.txt
}
}
}
Should I go about it via invoke-command or registry query? I'm slowly picking things up so I'll continue my research but I was hoping to get some advice in the meantime.
I still believe searching the registry is the easier way to go unless you have the specific file path for the .exe.
Use this function to find software on a remote, or local PC. Theres a filter option by specifying -SoftwareName (to look for).
Find-Software -ComputerName Remote_ComputerName -SoftwareName 'SQL'
Also accepts pipeline input, as well as multiple computer names to query for.
Find-Software -ComputerName ComputerOne, ComputerTwo, ComputerThree -SoftwareName 'SQL'
'ComputerOne','ComputerTwo' | Find-Software -SoftwareName 'SQL'
Exporting is also allowed by piping to an Export-* cmdlet.
Heres the code:
Function Find-Software {
[cmdletBinding()]
Param(
[Parameter(Mandatory=$false,
ValueFromPipeLine=$true,
ValueFromPipeLineByPropertyName=$true)]
[Alias('cn','name')]
[string[]]$ComputerName = $env:COMPUTERNAME,
[Parameter(Mandatory=$false)]
[String]$SoftwareName
)
Begin{
#Get Computer Names to check software version for
$Server_List = Get-Content -Path "C:\files\Serverlist.txt"
#Get Credentials for Script Scope once.
$Credentials = Get-Credential
}
Process{
if($PSBoundParameters.ContainsKey('SoftwareName')){
foreach($Computer in $ComputerName){
Try{
$PSSession = New-PSSession -ComputerName $Computer -Credential $Credentials -EnableNetworkAccess -ErrorAction Stop
$Software_List = Invoke-Command -ScriptBlock {
Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" } -Session $PSSession
$Software_List = $Software_List | Where-Object -FilterScript {$_.DisplayName -match $SoftwareName} | Sort-Object -Property DisplayName
foreach($Software in $Software_List){
if($Software){
[PSCustomObject]#{
"Computer Name" = $Computer
"Software Name" = $Software.DisplayName
" Version " = $Software.DisplayVersion
}
} else {
[PSCustomObject]#{
"Computer Name" = $Computer
"Software Name" = "Not found"
" Version " = $null
}
}
}
} Catch {
"Unable to connect to PC: $Computer"
"Error: $($Error[0].Message.Split('.')[1].Trim())"
}
}
} else {
foreach($Computer in $ComputerName){
Try{
$PSSession = New-PSSession -ComputerName $Computer -Credential $Credentials -EnableNetworkAccess -ErrorAction Stop
$Software_List = Invoke-Command -ScriptBlock {
Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*",
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" } -Session $PSSession
$Software_List = $Software_List | Sort-Object -Property DisplayName
foreach($Software in $Software_List){
[PSCustomObject]#{
"Computer Name" = $Computer
"Software Name" = $Software.DisplayName
" Version " = $Software.DisplayVersion
}
}
} Catch {
"Unable to connect to PC: $Computer"
"Error: $($Error[0].Message.Split('.')[1].Trim())"
}
}
} #end ELSE statement
} #end PROCESS block
End {
if(Get-PSSession){
Get-PSSession | Remove-PSSession
}
} #end END block - Perform Session Clean Up
} #end FUNCTION
Simply modify it to fit your needs :)

script tuning for include all computers in domain

I have a script which scans given computers in domain for identifying and disables mobile hotspot function in windows 10. Script works properly , but i want to scan all my domain comupters, not only specified.. can anyone help me for adjusting this script?
$username = "domain\administrator"
$password = "Your password"
$credential = New-Object System.Management.Automation.PSCredential -ArgumentList $username, $password
$computers = #("nr1", "nr2", "nr3")
foreach($computer in $computers){
$hotspot = Invoke-Command -ComputerName $computer -credential $credential -scriptblock {
$hotspot = Get-Service "icssvc"
if($hotspot.Status -eq "Running"){
Write-Host "Hotspot is turned on on $computer" -ForegroundColor Red
try{
Stop-Service "icssvc"
Write-Host "Successfully stopped service on $computer" -ForegroundColor Green
}catch{
Write-Host "Unable to stop service on $computer" -ForegroundColor Red
}
}else{
Write-Host "No Hotspot running on $computer" -ForegroundColor Green
}
}
If you replace $computers = #("nr1", "nr2", "nr3") with something like:
Import-Module ActiveDirectory
$computers = Get-ADComputer -Properties DNSHostName
That should return an array of hostnames. You may need to provide credentials via -Credential, and you can -Filter the results if you need to exclude any machines.
See docs and examples of Get-ADComputer here.

Check the AppPool status through power-shell and start that on remote machine

The requirement is to extract the server name one by one and check the AppPool status, if that is found to be stopped, make it running. below code is not helping out.
$ErrorActionPreference = "Continue"
$status = gc -path "D:\Servers\server.txt"|ForEach-Object (invoke-command -ComputerName $_ -ScriptBlock {Import-Module Webadministration Get-WebAppPoolState -name (gc "D:\AppPool.txt")})
if ($status.value -eq "Started")
{
Write-Host ("ApppPool already running")
}
else
{
Invoke-Command -ScriptBlock {Start-WebAppPool}
Write-host ("AppPool has started successfully")
}
There were multiple problems with your code, I've gone through them individually so you can see what was stopping it from working correctly.
The syntax for foreach was wrong, you needed to use {} not () in this case. Normal brackets are only used like this ForEach ($number in $numArray ) {CODE} which you aren't.
You were checking $status outside the foreach loop - so it so was evaluating $status only once (with the final computers AppPool status) rather than for each computer.
Your second Invoke-Command didn't have a ComputerName parameter specified so was only running the command locally not against the remote computer, meaning the AppPool would never be started.
As you were specifying the AppPool name using gc "D:\AppPool.txt" this file would have to be present on every remote computer for it to work. I've changed this to be passed into the command as an argument so the file only needs to be on the computer running the script.
$Credentials = Get-Credential
$AppPools = Get-Content "D:\AppPool.txt"
$Servers = Get-Content -Path "D:\Servers\server.txt"
ForEach ($Server in $Servers) {
ForEach ($AppPool in $AppPools) {
$AppPoolState = Invoke-Command -ComputerName $Server -ScriptBlock {Import-Module WebAdministration; Get-WebAppPoolState -Name $args[0] } -ArgumentList $AppPool -Credential $Credentials
if ($AppPoolState.Value -eq "Started")
{
Write-Host "$AppPool AppPool already running on $Server"
}
else
{
Invoke-Command -ComputerName $Server -ScriptBlock {Start-WebAppPool -Name $args[0] } -ArgumentList $AppPool -Credential $Credentials
Write-Host "$AppPool AppPool started on $Server"
}
}
}
Note: I run a non-privileged account so have to supply Credentials. If the account you're running the script as has appropriate permissions to all the remote computers you can remove the three Credentials references.

PowerShell invoke commands failing

This powershell is designed to add a user to either the Admin, Remote Desktop Users/User group depending on AD Group.
I tested on a Windows 7 Workstation and it worked great. When I try on a Windows 2012 Server it only adds the user to "Remote Desktop User" and not "Users" Advice please:
$user = $UserName
$group = "Domain Admins"
$members = Get-ADGroupMember -Identity $group -Recursive | Select - ExpandProperty SamAccountName
If ($members -contains $user) {
$AdminGroup = [ADSI]"WinNT://$TargetServer/Administrators,group"
$User = [ADSI]"WinNT://$DomainName/$UserName,user"
$AdminGroup.Add($User.Path)
Start-Sleep -s 3
invoke-command -ComputerName $TargetServer {net localgroup administrators}
} Else {
$AdminGroup = [ADSI]"WinNT://$TargetServer/Remote Desktop Users,group"
$User = [ADSI]"WinNT://$DomainName/$UserName,user"
$AdminGroup.Add($User.Path)
Start-Sleep -s 3
invoke-command -ComputerName $TargetServer {net localgroup Remote Desktop Users}
$AdminGroup = [ADSI]"WinNT://$TargetServer/Users,group"
$User = [ADSI]"WinNT://$DomainName/$UserName,user"
$AdminGroup.Add($User.Path)
Start-Sleep -s 3
invoke-command -ComputerName $TargetServer {net localgroup Users}
}
Ok weird. If I reverse the "Remote Desktop User" and "User" code blocks, it works on both Server and Workstation. Weird but resolved. I would like to know why if anyone has an answer.

PowerShell remote PC shutdown, single PC

OU=_ is a private company name. I know it's restart, this is only for testing before it goes into the real hutdown process.
function Get-LastBootUpTime {
param (
$ComputerName
)
$OperatingSystem = Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName
[Management.ManagementDateTimeConverter]::ToDateTime($OperatingSystem.LastBootUpTime)
}
$Days = -0
$ShutdownDate = (Get-Date).adddays($days)
$ComputerList = Get-ADComputer -SearchBase 'OU=TEST-OU,OU=_,DC=_,DC=_' ` -Filter '*' | Select -EXP Name
$ComputerList | foreach {
$Bootup = Get-LastBootUpTime -ComputerName $_
Write-Host "$_ last booted: $Bootup"
if ($ShutdownDate -gt $Bootup) {
Write-Host "Rebooting Computer: $_" -ForegroundColor Red
restart-Computer $Computer -Force
}
else {
Write-Host "No need to reboot: $_" -ForegroundColor Green
}
}
I'm trying to shutdown all of the PCs in my company that run longer than 2 days. The script is kind of done, but it shows an error when it comes to the point:
restart-Computer $Computer -Force
If I type instead of $Computer, $ComputerList the script shuts down every PC in that OU, even if they didnt run longer than 2 days.
So it only takes one PC to run longer than 2 days to shut down the entire company, and that's not what I want.
How can I tell the script to only turn the PCs off, when they have already run more than 2 days?
Your $Computer is not defined. You should use:
Restart-Computer $_ -Force
But the better approach would be to collect all of the computers that should restart in a variable and then restart them altogether. Would work much faster:
$toBeRestarted = $ComputerList | Where-Object { $ShutdownDate -gt (Get-LastBootUpTime -ComputerName $_) }
Restart-Computer $toBeRestarted -Force
You may add some more logging around if you like