This is the first thing I have ever done with Powershell. The gist of the script is to do some base setup for my companies web server installation. Basically it should
Take a list of names
Make a user with that name
configure user make a folder with that name
make an application pool with that name
set application pool properties
set folder permissions for a group
The code is below.
Import-Module WebAdministration
#$apps = #('H','N1','N2')
foreach ($app in $apps){
## I need to check for if a user exists first
NET USER $app "password" /ADD
NET LOCALGROUP "iis_iusrs" $app /ADD
WMIC USERACCOUNT WHERE "Name=$app" SET PaswordExpires=False
#See if the application's folder exists
if (!(Test-Path("C:\inetpub\wwwroot\"+$app)))
{
New-Item -ItemType Directory -Force -Path C:\inetpub\wwwroot\$app
}
## See if the application Pool exists. If it doesn't then create it
if (!(Test-Path("IIS:\AppPools\"+$app)))
{
$appPool = New-Item ("IIS:\AppPools\"+$app)
$appPool.ProcessModel.identityType = 3
$appPool.ProcessModel.userName=$app
$appPool.ProcessModel.password="password"
$appPool.ProcessModel.idleTimeout=[TimeSpan]::FromMinutes(0)
$appPool.processModel.loadUserProfile="True"
$appPool.recycling.disallowOverlappingRotation = "True"
$appPool.recycling.disallowRotationOnConfigChange = "True"
$appPool.recycling.periodicRestart.time = [TimeSpan]::FromMinutes(0)
$appPool | Set-Item
$propPath = "IIS:\AppPools\"+$appPool
New-ItemProperty -Path $propPath -Name recycling.periodicRestart.schedule -Value #{value="00:06:00"}
}
}
$webserver = Hostname
if(!(Test-Path("C:\"+$webserver)))
{
$hostserver = Read-Host "What is the host server's name?"
New-Item -ItemType Directory -Force -Path C:\$webserver\$hostserver
}
if(!(Test-Path('C:\Temp')))
{
New-Item -ItemType Directory -Force -Path C:\Temp
}
$Acl_inetpub = Get-Acl C:\inetpub
$Acl_temp = Get-Acl C:\Temp
$Acl_windows_temp = Get-Acl C:\Windows\Temp
$Ar_iis = New-Object System.Security.AccessControl.FileSystemAccessRule(".\iis_iusrs","FullControl","ContainerInherit,ObjectInherit","None","Allow")
$Ar_users = New-Object System.Security.AccessControl.FileSystemAccessRule(".\users","FullControl","ContainerInherit,ObjectInherit","None","Allow")
$Acl_inetpub.SetAccessRule($Ar_iis)
$Acl_inetpub.SetAccessRule($Ar_users)
$Acl_temp.SetAccessRule($Ar_iis)
$Acl_temp.SetAccessRule($Ar_users)
$Acl_windows_temp.SetAccessRule($Ar_iis)
$Acl_windows_temp.SetAccessRule($Ar_users)
Set-Acl C:\inetpub $Acl_inetpub
Set-Acl C:\temp $Acl_temp
Set-Acl C:\Windows\Temp $Acl_windows_temp
My issue currently is.
$propPath = "IIS:\AppPools\"+$appPool
New-ItemProperty -Path $propPath -Name recycling.periodicRestart.schedule -Value #{value="00:06:00"}
I get a path error when I run this but I am not sure where the error is coming from. Also, is there a way to do this same thing but just using the object like I did the rest of the settings? So far I have not found a way to do this.
So I found the final issue thanks Randy Schuman's advice. I wasn't thinking about how I was using $app vs $appPool . I was just continuing the pattern of using the $appPool's object when I need to supply it the $appPools name which is just $app. When I switched that it worked.
Related
I can run this script perfectly on my SharePoint server, and the user's profile picture gets updated:
[Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")
[Reflection.Assembly]::LoadWithPartialName("Microsoft.Office.Server")
$siteurl = "http://SHAREPOINTSITE/"
try {
$site = New-Object Microsoft.SharePoint.SPSite($siteurl)
} catch {
New-Item -ItemType File -Path C:\Users\admin\Desktop -Name ERROR1.txt -Value $_.Exception.Message -Force
}
try {
$context = [Microsoft.Office.Server.ServerContext]::GetContext($site)
} catch {
New-Item -ItemType File -Path C:\Users\admin\Desktop -Name ERROR2.txt -Value $_.Exception.Message -Force
}
#This gets the User Profile Manager which is what we want to get hold of the users
$upm = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
$user = "DOMAIN\user.name"
#Put it in a loop for iterating for all users
if ($upm.UserExists($user)) {
try {
$profile = $upm.GetUserProfile($user)
$profile["PictureURL"].Value = "\\Sharepoint\C$\Users\admin\Desktop\1.jpg";
$profile.Commit();
} catch {
New-Item -ItemType File -Path C:\Users\admin\Desktop -Name ERROR3.txt -Value $_.Exception.Message -Force
}
}
New-Item -ItemType File -Path C:\Users\admin\Desktop -Name HELLO.txt -Force
$site.Dispose()
But when I run it from a remote PowerShell session, I am getting some weird errors:
ERROR1.txt
Exception calling ".ctor" with "1" argument(s): "The Web application at http://SHAREPOINTSITE/ could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application."
ERROR2.txt
Multiple ambiguous overloads found for "GetContext" and the argument count: "1".
I have checked all of the possibilities here, but still seeing this issue.
This is how I call the above script from the remote machine:
$spfarm = "DOMAIN\admin.username"
$spfarmpw = ConvertTo-SecureString "password123" -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $spfarm,$spfarmpw
$session = New-PSSession SharePoint -Authentication Default -Credential $cred
Invoke-Command -Session $session -FilePath "\\SharePoint\C$\Users\admin\Desktop\testremote.ps1"
I have tried calling this in a few different ways (e.g. hosting the script on my machine or hosting it on the SharePoint server, as well as using relative paths to call the script), but I always see these errors.
Can anyone please help me understand why this doesn't work when calling it from a remote PC? The script is clearly being called (HELLO.txt always gets created), but the SharePoint profile picture never gets updated - even though that script definitely should work.
Any help or guidance is much appreciated
nslookup
nslookup SHAREPOINTSITE
Output
Server: dc1.domain.co.uk
Address: xx.xx.x.xx
Name: sharepoint.domain.co.uk
Address: yy.yy.y.yy
Aliases: SHAREPOINTSITE.domain.co.uk
Where yy.yy.y.yy is the correct IP (it's the same address I see when executing ping SHAREPOINTSITE)
Try changing the Authentication method to CredSSP. This is required by the remote PowerShell so that it can pass the credentials on.
I know you can enable Windows 10 Developer mode interactively by going to Settings | For developers, selecting 'Developer mode' and then rebooting.
Is there a way to enable this programmatically? (eg. via PowerShell or similar so that I can include it as a step in a Boxstarter script when refreshing my developer workstation)
Turns out Nickolaj Andersen has written an article which includes just such a PowerShell script..
http://www.scconfigmgr.com/2016/09/11/enable-ubuntu-in-windows-10-during-osd-with-configmgr/
Here are the relevant lines extracted from his post:
# Create AppModelUnlock if it doesn't exist, required for enabling Developer Mode
$RegistryKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
if (-not(Test-Path -Path $RegistryKeyPath)) {
New-Item -Path $RegistryKeyPath -ItemType Directory -Force
}
# Add registry value to enable Developer Mode
New-ItemProperty -Path $RegistryKeyPath -Name AllowDevelopmentWithoutDevLicense -PropertyType DWORD -Value 1
I modified the accepted answer and ended up with the following script:
param([Switch]$WaitForKey)
if (([Version](Get-CimInstance Win32_OperatingSystem).version).Major -lt 10)
{
Write-Host -ForegroundColor Red "The DeveloperMode is only supported on Windows 10"
exit 1
}
# Get the ID and security principal of the current user account
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
# Get the security principal for the Administrator role
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
if ($myWindowsPrincipal.IsInRole($adminRole))
{
$RegistryKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock"
if (! (Test-Path -Path $RegistryKeyPath))
{
New-Item -Path $RegistryKeyPath -ItemType Directory -Force
}
if (! (Get-ItemProperty -Path $RegistryKeyPath -Name AllowDevelopmentWithoutDevLicense))
{
# Add registry value to enable Developer Mode
New-ItemProperty -Path $RegistryKeyPath -Name AllowDevelopmentWithoutDevLicense -PropertyType DWORD -Value 1
}
$feature = Get-WindowsOptionalFeature -FeatureName Microsoft-Windows-Subsystem-Linux -Online
if ($feature -and ($feature.State -eq "Disabled"))
{
Enable-WindowsOptionalFeature -FeatureName Microsoft-Windows-Subsystem-Linux -Online -All -LimitAccess -NoRestart
}
if ($WaitForKey)
{
Write-Host -NoNewLine "Press any key to continue..."
$null = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
}
else
{
# We are not running "as Administrator" - so relaunch as administrator
# Create a new process object that starts PowerShell
$newProcess = new-object System.Diagnostics.ProcessStartInfo "PowerShell";
# Specify the current script path and name as a parameter
$newProcess.Arguments = "-NoProfile",$myInvocation.MyCommand.Definition,"-WaitForKey";
# Indicate that the process should be elevated
$newProcess.Verb = "runas";
# Start the new process
[System.Diagnostics.Process]::Start($newProcess);
# Exit from the current, unelevated, process
exit
}
It automatically elevates itself, if not already running elevated and enables the optional feature mentioned by Julian Knight.
I am trying to figure out how to write a powershell script that will set all .swf extensions to open up on Internet Explorer. I was trying to do this with a command prompt similar to the example below. Unfornately my boss is requiring this to be done through powershell. Any help with this would be greatly appreciated since I have a txt file that will loop through about 400 computers and need to make these changes on.
CMD Way
C:\>ASSOC .swf
.swf=ShockwaveFlash.ShockwaveFlash
C:\>FTYPE ShockwaveFlash.ShockwaveFlash
ShockwaveFlash.ShockwaveFlash="C:\bin\FlashPlayer.exe" %1
What I am Trying:
Function Get-FileName{
[CmdletBinding()]
Param(
[String]$Filter = "|*.*",
[String]$InitialDirectory = "C:\")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $InitialDirectory
$OpenFileDialog.filter = $Filter
[void]$OpenFileDialog.ShowDialog()
$OpenFileDialog.filename
}
$file = Get-FileName -InitialDirectory $env:USERPROFILE\Desktop -Filter "Text files (*.txt)|*.txt|All files (*.*)|*.*"
ForEach ($item in (Get-Content $file)) {
$sitem = $item.Split("|")
$computer = $sitem[0].Trim()
$user = $sitem[1].Trim()
cmd /c assoc .swf=InternetExplorer.Application
### Will the above line automatically install on every pc? ###
}
Any help with trying to insert how to change the FTYPE in powershell so that $computer can cycle through would be greatly appreciated!
ASSOC and FTYPE are CMD.exe built-in commands, not executables, which means they can only be run in the context of CMD. The easiest way to run them is to invoke CMD from PowerShell.
cmd /c assoc .swf
cmd /c ftype ShockwaveFlash.ShockwaveFlash
If you need a "pure" PowerShell implementation, then you need to go to the registry. ASSOC and FTYPE merely write to the registry under theHKEY_CLASSES_ROOT hive. PowerShell does not have a default PSDrive for HKCR:, but that hive is also accessible under HKLM:\Software\Classes.
$ext = '.swf'
$HKCR = 'HKLM:\Software\Classes'
$ftype = Get-ItemProperty -Path "$HKCR\$ext" | select -expand '(default)'
$commandLine = Get-ItemProperty -Path "$HKCR\$ftype\shell\open" | select -expand '(default)'
$commandLine
To update these values, you simply use Set-ItemProperty on the same path.
Set-ItemProperty -Path "$HKCR\$ext" -Name '(default)' -Value 'ShockwaveFlash.ShockwaveFlash'
This requires you to run with Admin privileges. This also assumes that the key already exists. If not, you will have to create it with New-Item
if (-not (Test-Path "$HKCR\$ext")) {
New-Item -Path "$HKCR\$ext"
}
However, if all you want to do is set .swf files to open in iexplore.exe, then retrieving the values is unnecessary, as is modifying the FTYPE key. You need only change the extension association to InternetExplorer.Application instead of ShockwaveFlash.ShockwaveFlash. The following full scripts will do this:
In Batch file:
assoc .swf=InternetExplorer.Application
In PowerShell:
cmd /c assoc .swf=InternetExplorer.Application
In "pure" PowerShell, by modifying the registry:
$key = "HKLM:\Software\Classes\.swf"
$defaultName = '(default)'
$newValue = 'InternetExplorer.Application'
if (-not (Test-Path $key)) {
New-Item -Path $key
}
Set-Itemproperty -Path $key -Name $defaultName -Value $newValue
Note that modifying the registry doesn't take effect immediately. You need to also send a WM_SETTINGCHANGE event, or simply restart explorer.exe (eg: by logging off). You can find code to send the event here, but usually this isn't a problem for automated scripts because they force the user to re-login anyway.
I would like to add \XX01234ABC01 to Local intranet zone using a PowerShell script and possibly take the site from the variable below.
$computername=$env:computername -replace ".....$","ABC01"
Any help would be much appreciated.
I hope this help you
$prefixIntranet = "www"
$LocalIntranetSite = "xxxx.com"
$UserRegPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains"
$DWord = 1
try {
Write-Verbose "Creating a new key '$LocalIntranetSite' under $UserRegPath."
New-Item -Path "$UserRegPath" -ItemType File -Name "$LocalIntranetSite"
New-Item -Path "$UserRegPath\$LocalIntranetSite" -ItemType File -Name "$prefixIntranet"
Write-Verbose "Creating a Dword value named 'HTTP' and set the value to '$DWord' "
Set-ItemProperty -Path $UserRegPath\$LocalIntranetSite\$prefixIntranet -Name "http" -Value $DWord `
Write-Host "Successfully added '$prefixIntranet.$LocalIntranetSite' domain to Internet Explorer local intranet."
} Catch [System.Exception] {
Write-Warning "[CATCH] Errors found during attempt:`n$_" -BackgroundColor Red
}
I was looking to do something similar. This will do the job:
# Gets you PC Name like you had in your question
$LocalIntranetSite = $env:computername -replace ".....$","ABC01"
# Set your base registry location
$UserRegPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet
Settings\ZoneMap\Domains"
# Set your zone. 1 is intranet.
$DWord = 1
try {
Write-Debug "Creating a new key '$LocalIntranetSite' under $UserRegPath."
# Check to be sure the key isn't already listed before trying to add
if (-not (Test-Path -Path "$UserRegPath\$LocalIntranetSite")) {
# Add your site to the domains list in the registry
New-Item -Path "$UserRegPath" -ItemType File -Name "$LocalIntranetSite"
}
# Set a Dword property named '*' and with value '$DWord' on your '$LocalIntranetSite'.
# This is what adds your site to the Intranet Zone.
Set-ItemProperty -Path "$UserRegPath\$LocalIntranetSite" -Name "*" -Value $DWord
} Catch [System.Exception] {
Write-Warning "[CATCH] Errors found during attempt:`n$_"
}
I have a question about Get-Acl in Powershell. I keep getting the error message, "Access to the path is denied". I want to change the owner of the folder to myself and then give myself full permissions to the folder using Powershell. Here's the line of code giving me the error:
$acl = Get-Acl "C:\SomeFolder"
I am using Windows Explorer to set the permissions on "SomeFolder" before running the script. They are as follows:
no entries in the access control list
owner is not myself
I do not receive the error message if I make myself the owner using the Windows Explorer GUI before running the Powershell script. I don't understand why I am allowed to change the owner with Windows Explorer but not using Powershell? I have full admin rights on this machine. Windows 7, Powershell 2.0, .NET 3.5.
I'm assuming the only way to change the owner is to use Get-Acl, set owner on the ACL, then use Set-Acl to write it back to the folder. If there is another way, please let me know? How can I change the owner of the folder using Powershell?
Windows Vista and up include a command-line tool named takeown.exe which can be used from an elevated command prompt (or elevated powershell console) to change the ownership of a file system object.
takeown /F "C:\SomeFolder" /R /D Y
should give you ownership on C:\SomeFolder and the file system objects it contains.
I have some system configuration scripts from our build guy and I recall a note about the Get-Acl command "not working well on certain paths".
# NOTE: This method does not work well?
#$acl = Get-Acl -Path $Path
The kinds of paths we were setting permissions on were empty folders created by an administrator user later captured in a disk image. This is the PowerShell command that we used instead.
$acl = (Get-Item $path).GetAccessControl("Access")
Oh, and it gets real obscure once you have an ACL object. I don't know if this is the best way to do it, but it's a snippet from the same script I refer to above.
$acl = (Get-Item $path).GetAccessControl("Access")
# Setup the access rule.
$allInherit = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit", "ObjectInherit"
$allPropagation = [System.Security.AccessControl.PropagationFlags]"None"
$AR = New-Object System.Security.AccessControl.FileSystemAccessRule $user, $permissions, $allInherit, $allPropagation, "Allow"
# Check if Access already exists.
if ($acl.Access | Where { $_.IdentityReference -eq $User})
{
$accessModification = New-Object System.Security.AccessControl.AccessControlModification
$accessModification.value__ = 2
$modification = $false
$acl.ModifyAccessRule($accessModification, $AR, [ref]$modification) | Out-Null
}
else
{
$acl.AddAccessRule($AR)
}
Set-Acl -AclObject $acl -Path $Path
the above code worked great. wanted to post a tweak for recursively going through directory and filling in some "missing"
$HomeFolders = Get-ChildItem "put your directory root here" -Directory -recurse
foreach ($HomeFolder in $HomeFolders) {
$Path = $HomeFolder.FullName
$acl = (Get-Item $Path).GetAccessControl('Access')
$allInherit = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit", "ObjectInherit"
$allPropagation = [System.Security.AccessControl.PropagationFlags]"None"
$permissions = "FullControl"
$Username = "<put your name here>"
$AR = New-Object System.Security.AccessControl.FileSystemAccessRule($Username, $permissions, $allInherit, $allPropagation, "Allow")
if ($acl.Access | Where { $_.IdentityReference -eq $Username})
{
$accessModification = New-Object System.Security.AccessControl.AccessControlModification
$accessModification.value__ = 2
$modification = $false
$acl.ModifyAccessRule($accessModification, $AR, [ref]$modification) | Out-Null
}
else
{
$acl.AddAccessRule($AR)
}
Set-Acl -path $Path -AclObject $Acl
}