Creating powershell script to get show on desktop enabled + rename with hostname - powershell

I'm just a junior programmer, just started with programming and because my work requests me to create some handy powershell scripts I was wondering if you can help me with a particular one.
We have a lot of customers with a lot of servers. When they are newly installed I do check them and after that we do regular maintenance. Because each customer has several servers with different roles I want to have the "Computer" icon on my desktop.
I can do that by clicking start -> rightclick Computer -> Enable "Show on Desktop"
Furtheron I want to have this Computer icon renamed to the hostname (because the hostname tells me it's role in the domain)
Now my goal is to create a powershell script that creates this computer icon with hostname for all the server in the domain.
I've tried to search my way to the usual search engines and came up with this:
1) Locate with regedit [HKEY_CLASSES_ROOT\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D} rename LocalizedString to LocalizedString.Old
2) Now switch to Regedit32 Create a new VALUE type Expand_SZ name it LocalizedString On XP and Windows 2000 with SP3 replace LocalizedString with %Username% at %Computername%
Which isn't suitable because we use W2K8R2SP1 servers.
After that I ended up with this script:
$ComputerName = "Localhost"
$Hive = "CurrentUser"
$Key = "Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"
$MyComputer = "{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
$UserFiles = "{59031a47-3f72-44a7-89c5-5595fe6b30ee}"
$Kind = [Microsoft.Win32.RegistryValueKind]
$RegHive = [Microsoft.Win32.RegistryHive]$hive
$RegKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegHive,$ComputerName)
$MyComputerValue = ($RegKey.OpenSubKey($Key)).GetValue($MyComputer)
$UserFilesValue = ($RegKey.OpenSubKey($Key)).GetValue($UserFiles)
if ($MyComputerValue -eq $null -or $MyComputerValue -eq 0)
{
$Computer = $regKey.OpenSubKey($RootKey,$true)
$Computer.SetValue($MyComputer, 1,$Kind::DWord)
}
if ($UserFilesValue -eq $null -or $UserFilesValue -eq 0)
{
$User = $regKey.OpenSubKey($RootKey,$true)
$User.SetValue($UserFiles, 1,$Kind::DWord)
}
This doesn't seem to be doing anything at all.
I know this registry key is used for the computer on desktop:
“{20D04FE0-3AEA-1069-A2D8-08002B30309D}”=dword:00000000
Continued search...
So I found this:
To show the ‘My Computer’ icon on the desk"text-decoration:underline;">
[HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel]
Name = {20D04FE0-3AEA-1069-A2D8-08002B30309D}
Type =REG_DWORD
Value = 0
To change the ‘My Computer’ icon to computer or user name:
[HKCR\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}]
Name = LocalizedString
Type = REG_EXPAND_SZ
Data value = %computername% or any combination you like – eg %username% %computername%
However the second part keeps giving me an error and even if i can get it to work, i want to run the script onces and all servers in domain should be having this update.
Thanks for helping out.
Best regards,
Nick

Changing HKCR\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\LocalizedString is still suitable on Server 2008 R2, but you need to take ownership of the key and grant administrators full access to it first.

Related

Having trouble setting Remote Desktop Services Control permissions?

I am new to power shell and I am trying to create a script that would create new users in Active Directory. Currently I am having trouble setting the Remote Desktop Services tab of the User. My code is below.
#Set Remote Control Settings Permissions
#I recieved Server is not operational error. https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/fail-to-configure-server-using-server-manager I think Invoke Set may not be the command I should use.
$userpath = dsquery user -samid $username
$userpat = "LDAP://$userpath"
$userp = [ADSI]$userpat
$userp.InvokeSet("EnableRemoteControl",2)
$userp.setinfo()
#Remote Desktop Services User profile profile path set to "\\documentsf\profiles\$username" THIS IS MESSING UP ERROR OCCURRS WITH INVOKE SET SAYING NOT SPECIFIED
$userp.InvokeSet("terminalservicesprofilepath","\\documentsf\profiles\$username")
$userp.setinfo()
The remote control permissions are a little strange and work best with the ADSI method, which you're close to already. dsquery actually returns a string with quotes inside it, so you'll either need to strip those quotes first or use a different method - I prefer Get-ADUser:
$LdapUser = "LDAP://" + (Get-ADUser $username).distinguishedName
$User = [ADSI]$LdapUser
$User.InvokeSet("EnableRemoteControl",2)
$User.setinfo()
And to set the remote desktop services profile path for a user:
$User.invokeset("terminalservicesprofilepath","\\Server\Share\$username")
$User.SetInfo()

Running Command as Administrator from a SYSTEM Process

So I need to clear a user's run dialog history which I can do perfectly fine with "reg delete HKEY_CURRENT_USER\Software\Windows etc..." from an elevated powershell window on the logged in user's machine, but what I'm looking to do is that same command but from a SYSTEM powershell process. I have already used psexec to create a powershell window which runs as SYSTEM, but because you can't just use HKEY_CURRENT_USER as SYSTEM with the same results, I am finding it quite difficult. If I could just run that command but as username\Administrator then I wouldn't have this problem.
Also to note, if I can somehow grab the username of the logged on user (from SYSTEM still) in one line in plain text (with no other output in sight), then I can store the username in a variable and convert that to an SID and use HKEY_USERS instead.
P.S. Don't ask why I'm running powershell as SYSTEM, I know what I'm doing :D
you can use get-process under the system context powershell and filter where explorer.exe process is running, get the account it is running under then use to convert to SID and go through the registry.
something like this assuming only 1 explorer.exe process is running which is the norm on windows client OS.
$proc = Get-CimInstance Win32_Process -Filter "name = 'explorer.exe'"
$owner = Invoke-CimMethod -InputObject $proc -MethodName GetOwner
$username = $owner.user
$username will contain the user, $owner will also contain domain and a few other things.
to convert to sid
$objUser = New-Object System.Security.Principal.NTAccount($owner.Domain, $owner.User)
$strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
$strSID.Value

How can I manage local useraccounts on windows server 2008 r2 with powershell?

I should create, activate and deactivate local user accounts on windows server 2008 r2 with powershell. I already do it with active directory, but I don't find the commands for local accounts. Can anyone help me?
Best regards.
Karl
I'm sorry if I were not as accurate as I should be. I have to do it for the local user account on a member server, not on domain-controller.
When you install Active Directory, it removes any local accounts. This is intended.
This question would be better suited for https://serverfault.com/
function create-account ([string]$accountName, [string]$accountDescription) {
$hostname = hostname
$comp = [adsi]"WinNT://$hostname"
$user = $comp.Create("User", $accountName)
$user.SetPassword("change,password.10")
$user.SetInfo()
$user.description = $accountDescription
$user.SetInfo()
$User.UserFlags[0] = $User.UserFlags[0] -bor 0×10000 #ADS_UF_DONT_EXPIRE_PASSWD flag is 0×10000
$user.SetInfo()
$objOU = [ADSI]"WinNT://$hostname/Administrators,group"
$objOU.add("WinNT://$hostname/$accountName")
$objOU = [ADSI]"WinNT://$hostname/Remote Desktop Users,group"
$objOU.add("WinNT://$hostname/$accountName")
}
create-account "testuser2" "Some Description"
Save thats as .ps1, edit info to suit and then run it.
http://www.jrdata.se/2012/10/31/add-local-users-with-powershell/

Correctly set the current user as the new owner in PowerShell [duplicate]

How do I get the current username in Windows PowerShell?
I found it:
$env:UserName
There is also:
$env:UserDomain
$env:ComputerName
On Windows, you can:
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
I thought it would be valuable to summarize and compare the given answers.
If you want to access the environment variable:
(easier/shorter/memorable option)
[Environment]::UserName -- #ThomasBratt
$env:username -- #Eoin
whoami -- #galaktor
If you want to access the Windows access token:
(more dependable option)
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name -- #MarkSeemann
If you want the name of the logged in user
(rather than the name of the user running the PowerShell instance)
$(Get-WMIObject -class Win32_ComputerSystem | select username).username -- #TwonOfAn on this other forum
Comparison
#Kevin Panko's comment on #Mark Seemann's answer deals with choosing one of the categories over the other:
[The Windows access token approach] is the most secure answer, because $env:USERNAME can be altered by the user, but this will not be fooled by doing that.
In short, the environment variable option is more succinct, and the Windows access token option is more dependable.
I've had to use #Mark Seemann's Windows access token approach in a PowerShell script that I was running from a C# application with impersonation.
The C# application is run with my user account, and it runs the PowerShell script as a service account. Because of a limitation of the way I'm running the PowerShell script from C#, the PowerShell instance uses my user account's environment variables, even though it is run as the service account user.
In this setup, the environment variable options return my account name, and the Windows access token option returns the service account name (which is what I wanted), and the logged in user option returns my account name.
Testing
Also, if you want to compare the options yourself, here is a script you can use to run a script as another user. You need to use the Get-Credential cmdlet to get a credential object, and then run this script with the script to run as another user as argument 1, and the credential object as argument 2.
Usage:
$cred = Get-Credential UserTo.RunAs
Run-AsUser.ps1 "whoami; pause" $cred
Run-AsUser.ps1 "[System.Security.Principal.WindowsIdentity]::GetCurrent().Name; pause" $cred
Contents of Run-AsUser.ps1 script:
param(
[Parameter(Mandatory=$true)]
[string]$script,
[Parameter(Mandatory=$true)]
[System.Management.Automation.PsCredential]$cred
)
Start-Process -Credential $cred -FilePath 'powershell.exe' -ArgumentList 'noprofile','-Command',"$script"
(you may need a hyphen before noprofile, like so)
Start-Process -Credential $cred -FilePath 'powershell.exe' -ArgumentList '-noprofile','-Command',"$script"
$env:username is the easiest way
I'd like to throw in the whoami command, which basically is a nice alias for doing %USERDOMAIN%\%USERNAME% as proposed in other answers.
Write-Host "current user:"
Write-Host $(whoami)
[Environment]::UserName returns just the user name. E.g. bob
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name returns the user name, prefixed by its domain where appropriate. E.g. SOMEWHERENICE\bob
Now that PowerShell Core (aka v6) has been released, and people may want to write cross-platform scripts, many of the answers here will not work on anything other than Windows.
[Environment]::UserName appears to be the best way of getting the current username on all platforms supported by PowerShell Core if you don't want to add platform detection and special casing to your code.
I have used $env:username in the past, but a colleague pointed out it's an environment variable and can be changed by the user and therefore, if you really want to get the current user's username, you shouldn't trust it.
I'd upvote Mark Seemann's answer:
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name
But I'm not allowed to. With Mark's answer, if you need just the username, you may have to parse it out since on my system, it returns hostname\username and on domain joined machines with domain accounts it will return domain\username.
I would not use whoami.exe since it's not present on all versions of Windows, and it's a call out to another binary and may give some security teams fits.
Just building on the work of others here:
[String] ${stUserDomain},[String] ${stUserAccount} = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name.split("\")
$username=( ( Get-WMIObject -class Win32_ComputerSystem | Select-Object -ExpandProperty username ) -split '\\' )[1]
$username
The second username is for display only purposes only if you copy and paste it.
I didn't see any Add-Type based examples. Here is one using the GetUserName directly from advapi32.dll.
$sig = #'
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool GetUserName(System.Text.StringBuilder sb, ref Int32 length);
'#
Add-Type -MemberDefinition $sig -Namespace Advapi32 -Name Util
$size = 64
$str = New-Object System.Text.StringBuilder -ArgumentList $size
[Advapi32.util]::GetUserName($str, [ref]$size) |Out-Null
$str.ToString()
Sometimes the Username attribute has no data in Win32_ComputerSystem even though there's a user signed in. What works for me is to use quser and parse the output. It's not perfect, but it works. E.g.:
$quserdata = #()
$quserdata = quser
$userid = ($quserdata[1] -split ' ')[1]
$userid
Note: if this is run as the user who is logged in, quser adds '>' symbol to the output. Then you need to get rid of that symbol, but mostly this is needed for code run as system or another account than the one that is logged in.
If you're used to batch, you can call
$user=$(cmd.exe /c echo %username%)
This basically steals the output from what you would get if you had a batch file with just "echo %username%".
I find easiest to use: cd $home\Desktop\
will take you to current user desktop
In my case, I needed to retrieve the username to enable the script to change the path, ie. c:\users\%username%. I needed to start the script by changing the path to the users desktop. I was able to do this, with help from above and elsewhere, by using the get-location applet.
You may have another, or even better way to do it, but this worked for me:
$Path = Get-Location
Set-Location $Path\Desktop
In my case, I needed to retrieve the username to enable the script to change the path, ie. c:\users\%username%\. I needed to start the script by changing the path to the users desktop. I was able to do this, with help from above and elsewhere, by using the get-location applet.
You may have another, or even better way to do it, but this worked for me:
$Path = Get-Location
Set-Location $Path\Desktop

Adding computer to Event Log Readers group using Powershell Commands

I need to add the computer to the Event Log Readers group. I had tried the below script.
$hostName = "Hostname"
$computername = $env:computername
$EventLogGroup = [adsi]"WinNT://$computername/Event Log Readers,group"
$temp = "WinNT://$hostName"
$EventLogGroup.Add($temp)
The same script worked for adding the user to group and for adding the computers its not adding.
Object types we need to change to Computers I think. Locations will be in same domain.
Any modifications or alternative script will be helpful
"A member could not be added to or removed from the local group because the member does not exist" this is the error I am getting while executing the script
Try to add the domain name and a dollar sign after the computer name:
$temp = "WinNT://DomainName/$hostName$,computer"