I should start off by stressing that I have very, very little experience in PowerShell, so apologies if this is user error.
After copying the commands over from https://learn.microsoft.com/en-us/troubleshoot/developer/browsers/administration/k-12-assessments-reports-apps-background I keep hitting Unexpected Token errors on step 4. This is the code, along with the errors:
$registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\PreLaunch\Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge" $Name = "Enabled" $value = "0" New-Item -Path $registryPath -Force | Out-Null New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null
At line:1 char:138
... ch\Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge" $Name = "Enab ...
~~~~~
Unexpected token '$Name' in expression or statement.
At line:1 char:156
... oftEdge_8wekyb3d8bbwe!MicrosoftEdge" $Name = "Enabled" $value = "0" N ...
~~~~~~
Unexpected token '$value' in expression or statement.
At line:1 char:169
... d8bbwe!MicrosoftEdge" $Name = "Enabled" $value = "0" New-Item -Path $ ...
~~~~~~~~
Unexpected token 'New-Item' in expression or statement.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : UnexpectedToken
I've tried messing around with a few things and have gotten rid of some, but not all of the errors. Any help would be greatly appreacited!
Sample formatting on that documentation article is broken, it's hiding a couple of linebreaks:
$registryPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\PreLaunch\Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge"
$Name = "Enabled"
$value = "0"
New-Item -Path $registryPath -Force | Out-Null
New-ItemProperty -Path $registryPath -Name $name -Value $value -PropertyType DWORD -Force | Out-Null
Related
I am trying to get a script working to audit folder permissions on a Windows server, among other data, and export this data to a CSV file for analysis after a ransomware attack.
I ripped the script from a forum, but it did not run correctly as is. Below is a slightly modified version during my troubleshooting.
I am well versed in batch scripting, and have a decent understanding of loops and pipelining, but this Powershell script has me scratching my head.
It seems like the array is not making it to the nested loop.
I am testing in Windows 10 Pro 21H1, using Powershell version 5.1.19041.1320, build 10.0.19041.1320
##The script:
$ErrorActionPreference = "Continue"
$strComputer = $env:ComputerName
$colDrives = Get-PSDrive -PSProvider Filesystem
ForEach ($DriveLetter in $colDrives) {
$StartPath = "$DriveLetter`:\"
Get-ChildItem -LiteralPath $StartPath -Recurse | ?{ $_.PSIsContainer } |
ForEach ($FullPath = Get-Item -LiteralPath{Get-Item -LiteralPath $_.PSPath}{Get-Item -
LiteralPath $FullPath}.Directoryinfo.GetAccessControl())}
Select #{N='Server Name';E={$strComputer}}
#{N='Full Path';E={$FullPath}}
#{N='Type';E={If($FullPath.PSIsContainer -eq $True) {'D'} Else {'F'}}}
#{N='Owner';E={$_.Owner}}
#{N='Trustee';E={$_.IdentityReference}}
#{N='Inherited';E={$_.IsInherited}}
#{N='Inheritance Flags';E={$_.InheritanceFlags}}
#{N='Ace Flags';E={$_.PropagationFlags}}
#{N='Ace Type';E={$_.AccessControlType}}
#{N='Access Masks';E={$_.FileSystemRights}}
Export-CSV -NoTypeInformation -Delimiter "|" -Path "$strComputer`_$DriveLetter.csv"
##The error I am getting:
You cannot call a method on a null-valued expression.
At C:\Users\user\Documents\fileaudit2.ps1:8 char:13
ForEach ($FullPath = Get-Item -LiteralPath{Get-Item -LiteralPath $ ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidOperation: (:) [], RuntimeException
FullyQualifiedErrorId : InvokeMethodOnNull
##when I modify the nested loop as follows:
ForEach ($FullPath = Get-Item -LiteralPath{Get-Item -LiteralPath $_.PSPath}{Get-Item -LiteralPath $FullPath}).Directoryinfo.GetAccessControl()}
##I get the error:
Get-Item : Cannot evaluate parameter 'LiteralPath' because its argument is specified as a script block and there is no input. A script block cannot be evaluated without
input.
At C:\Users\user\Documents\fileaudit2.ps1:8 char:46
... Path = Get-Item -LiteralPath{Get-Item -LiteralPath $_.PSPath}{Get-Ite ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : MetadataError: (:) [Get-Item], ParameterBindingException
FullyQualifiedErrorId : ScriptBlockArgumentNoInput,Microsoft.PowerShell.Commands.GetItemCommand
##I'm just wholly struggling to understand what is not working in this loop.
You are mixing a lot of unneeded Get-Item calls in there.
I also would not use Get-PSDrive for this because I assume you don't want to get results for CD drives, USB devices etc in the report.
Try:
# this returns drives WITH a trailing backslash like C:\
$colDrives = ([System.IO.DriveInfo]::GetDrives() | Where-Object { $_.DriveType -eq 'Fixed' }).Name
# or use:
# this returns drives WITHOUT trailing backslash like C:
# $colDrives = (Get-CimInstance -ClassName win32_logicaldisk | Where-Object { $_.DriveType -eq 3 }).DeviceID
$result = foreach ($drive in $colDrives) {
Get-ChildItem -LiteralPath $drive -Directory -Recurse -ErrorAction SilentlyContinue |
ForEach-Object {
$path = $_.FullName
$acl = Get-Acl -Path $path
foreach ($access in $acl.Access) {
[PsCustomObject]#{
Server = $env:COMPUTERNAME
Drive = $drive[0] # just the first character of the drive
Directory = $path
Owner = $acl.Owner
Trustee = $access.IdentityReference
Inherited = $access.IsInherited
InheritanceFlags = $access.InheritanceFlags -join ', '
'Ace Flags' = $access.PropagationFlags -join ', '
'Ace Type' = $access.AccessControlType
'Access Masks' = $access.FileSystemRights -join ', '
}
}
}
}
# now you can save your result as CSV file for instance you can double-click to open in Excel:
$result | Export-Csv -Path 'X:\WhereEver\audit.csv' -NoTypeInformation -UseCulture
To do this on several remote machines, wrap it inside Invoke-Command
# set the credentials for admin access on the servers
$cred = Get-Credential 'Please enter your admin credentials'
# create an array of the servers you need to probe
$servers = 'Server01', 'Server02'
$result = Invoke-Command -ComputerName $servers -Credential $cred -ScriptBlock {
$colDrives = ([System.IO.DriveInfo]::GetDrives() | Where-Object { $_.DriveType -eq 'Fixed' }).Name
foreach ($drive in $colDrives) {
# code inside this loop unchanged as above
}
}
# remove the extra properties PowerShell added
$result = $result | Select-Object * -ExcludeProperty PS*, RunspaceId
# output to csv file
$result | Export-Csv -Path 'X:\WhereEver\audit.csv' -NoTypeInformation -UseCulture
I am trying to configure a new RDS gateway server through Powershell (for automatic setup after EC2 creation). The issue I'm running into right now is setting up a default or otherwise CAP and RAP. Everything else seems to work just fine, and if I go through the server dialogs and point and click my way to doing the CAP/RAP wizard, it all works. Until I do so, those policies don't exist (not even a default).
The code I'm using, which I sourced from blog posts on technet about the subject, is this:
new-item -Force -Credential $AdminCredentials -path RDS:\GatewayServer\CAP -Name DomainAdmin-CAP -UserGroups “$AdminGroupName#$NetBiosDomainName" -AuthMethod 1
new-item -Force -Credential $AdminCredentials -path RDS:\GatewayServer\CAP -Name DomainUser-CAP -UserGroups “$UserGroupName#$NetBiosDomainName" -AuthMethod 1
new-item -Force -Credential $AdminCredentials -path RDS:\GatewayServer\RAP -Name DomainAdmin-RAP -UserGroups “$AdminGroupName#$NetBiosDomainName" -ComputerGroupType 2
new-item -Force -Credential $AdminCredentials -path RDS:\GatewayServer\RAP -Name DomainUser-RAP -UserGroups “$UserGroupName#$NetBiosdomainName" -ComputerGroupType 2
Again, everything else works and the system is 100% and useable once I RDP in to the server and set these up manually, so my only issue is this automation step. The error I'm getting when I run my script is this:
new-item : Access to the object at RDS:\GatewayServer\CAP\DomainAdmin-CAP is denied for the cmdlet
New-Item.The supplied value is not valid, or you do not have
sufficient permissions. At line:89 char:1
+ new-item -Force -Credential $AdminCredentials -path RDS:\GatewayServe ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (:) [New-Item], AccessViolationException
+ FullyQualifiedErrorId : PermissionDenied,Microsoft.PowerShell.Commands.NewItemCommand
Edit: Things I have tried based on suggestions and frustration:
I have made all " characters uniform after someone pointed out they were actually not the same thing on the front and rear of my -UserGroup variable strings - No error change.
I have tried $NetBiosDomainName as the simple one word NetBIOS version (DOMAIN) as well as the full domain (domain.company.com) - No error change.
I have tried changing the "$AdministratorsGroupName#$NetBiosDomainName" string out for $AdminGroup (= $AdministratorsGroupName + "#" + $NetBiosDomainName") to simplify the input to the -UserGroups parameter - No error change
I have run this script as both the domain admin and local administrator account - No error change
I was able to use the following script to configure a Remote Access Gateway on a non-domain Windows 2019/2016 server. This includes a CAP, a RAP, and a ManagedComputerGroup.
Install-WindowsFeature -Name "RDS-Gateway" -IncludeAllSubFeature -IncludeManagementTools > $null
Import-Module -Name RemoteDesktopServices
#=============User Modifiable=============#
$GroupName="SG_RemoteUsers#$env:COMPUTERNAME"
# No Restrictions
#$GroupName="Users#BUILTIN"
$ManagedComputers="RDG_RDCBComputers"
# Managed Computer Groups
$MCGComputers=#($env:COMPUTERNAME,"<target machines>")
$MCGs=#(#{Name="RDG_RDCBComputers";Desc="All RDCB Computers in the deployment";Computers=$MCGComputers})
# Connection Authorization Policies
$CAPs=#(#{Name="RDG_CAP_AllUsers";UserGroups=$GroupName;AuthMethod=1;Status=1})
# Resrouce Authorization Policies
$RAPs=#(#{Name="RDG_AllComputers";UserGroups=$GroupName;ComputerGroupType=2;ComputerGroup=$null})
# If you already have a certificate, skip this part.
<#region Certificate
$FilePath="C:\temp\export.cer"
$SelfSigned=New-SelfSignedCertificate -CertStoreLocation "Cert:\LocalMachine\My" -DnsName $env:COMPUTERNAME -FriendlyName $env:COMPUTERNAME -KeyAlgorithm "RSA" -HashAlgorithm "SHA256" -KeyDescription "RDG Key" -KeyLength 4096 -KeyUsage KeyEncipherment,DataEncipherment -KeyUsageProperty All
$CertPassword=ConvertTo-SecureString -String “password” -Force –AsPlainText
Export-PfxCertificate -Cert $SelfSigned.PSPath -FilePath $FilePath -Password $CertPassword > $null
Import-PfxCertificate -CertStoreLocation "Cert:\LocalMachine\Root" -FilePath $FilePath -Password $CertPassword > $null
Remove-Item -Path $FilePath
$Certificate=$SelfSigned
#endregion
#>
$Certificate=Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" } | Sort-Object -Property NotAfter -Descending | Select-Object -Last 1
#=============Do not modify=============#
$CAPPath="RDS:\GatewayServer\CAP"
$RAPPath="RDS:\GatewayServer\RAP"
$MCGPath="RDS:\GatewayServer\GatewayManagedComputerGroups"
#=============Script=============#
# Add the certificate to RDS
Set-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint" -Value $Certificate.Thumbprint
try { Get-LocalGroup -Name $GroupName -ErrorAction Stop > $null }
catch { New-LocalGroup -Name $GroupName > $null }
try { Get-LocalGroupMember -Group $GroupName -Member "<user that should have access>" -ErrorAction Stop > $null }
catch { Add-LocalGroupMember -Group $GroupName -Member "<user that should have access>" > $null }
# Remove existing items (must be done in the order of CAP and/or RAP first, then GatewayManagedComputerGroups
$CAPs | ForEach-Object { if (Test-Path -Path "$CAPPath\$($_.Name)") { Remove-Item -Path "$CAPPath\$($_.Name)" -Recurse } }
$RAPs | ForEach-Object { if (Test-Path -Path "$RAPPath\$($_.Name)") { Remove-Item -Path "$RAPPath\$($_.Name)" -Recurse } }
$MCGs | ForEach-Object { if (Test-Path -Path "$MCGPath\$($_.Name)") { Remove-Item -Path "$MCGPath\$($_.Name)" -Recurse } }
$MCGs | ForEach-Object { New-Item -Path $MCGPath -Name $_.Name -Description $_.Desc -Computers $_.Computers > $null }
$CAPs | ForEach-Object { New-Item -Path $CAPPath -Name $_.Name -UserGroups $_.UserGroups -AuthMethod $_.AuthMethod -Status $_.Status > $null }
$RAPs | ForEach-Object { New-Item -Path $RAPPath -Name $_.Name -UserGroups $_.UserGroups -ComputerGroupType $_.ComputerGroupType > $null }
# Stop redirection of Serial Ports
$CAPs | ForEach-Object { Set-Item -Path "$CAPPath\$($_.Name)\DeviceRedirection\SerialPorts" -Value 0 }
Restart-Service -Name "TSGateway"
This script, which shares a significant portion of the previous, is what I used to configure the same on a server that is a member of an AD domain. It's not the only way to do it, but hopefully it will give you a head start.
There is a portion of this script that creates the necessary AD group.
The only part that's missing is that the certificate must be placed in the Trusted Root store on the PC from which you want to connect.
Install-WindowsFeature -Name "RDS-Gateway" -IncludeAllSubFeature -IncludeManagementTools > $null
Import-Module -Name RemoteDesktopServices
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
#=============User Modifiable=============#
$GroupName="SG_RemoteUsers"
$ManagedComputers="RDG_RDCBComputers"
# Managed Computer Groups
$MCGComputers=#($env:COMPUTERNAME,"<target machines>")
$MCGs=#(#{Name=$ManagedComputers;Desc="All RDCB Computers in the deployment";Computers=$MCGComputers})
# Connection Authorization Policies
$CAPs=#(#{Name="RDG_CAP_AllUsers";UserGroups="$GroupName#$env:USERDOMAIN";AuthMethod=1;Status=1})
# Resrouce Authorization Policies
$RAPs=#(#{Name="RDG_AllDomainComputers";UserGroups="$GroupName#$env:USERDOMAIN";ComputerGroupType=1;ComputerGroup="Domain Computers#$env:USERDOMAIN"},
#{Name="RDG_RDConnectionBrokers";UserGroups="Domain Users#$env:USERDOMAIN";ComputerGroupType=0;ComputerGroup=$ManagedComputers})
# If you already have a certificate, skip this part.
<#region Certificate
$FilePath="C:\temp\export.cer"
$SelfSigned=New-SelfSignedCertificate -CertStoreLocation "Cert:\LocalMachine\My" -DnsName "$env:COMPUTERNAME.$env:USERDNSDOMAIN" -FriendlyName $env:COMPUTERNAME -KeyAlgorithm "RSA" -HashAlgorithm "SHA256" -KeyDescription "RDG Key" -KeyLength 4096 -KeyUsage KeyEncipherment,DataEncipherment -KeyUsageProperty All
$CertPassword=ConvertTo-SecureString -String “password” -Force –AsPlainText
Export-PfxCertificate -Cert $SelfSigned.PSPath -FilePath $FilePath -Password $CertPassword > $null
Import-PfxCertificate -CertStoreLocation "Cert:\LocalMachine\Root" -FilePath $FilePath -Password $CertPassword > $null
Remove-Item -Path $FilePath
$Certificate=$SelfSigned
#endregion
#>
$Certificate=Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object { $_.Thumbprint -eq "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" } | Sort-Object -Property NotAfter -Descending | Select-Object -Last 1
#=============Do not modify=============#
$CAPPath="RDS:\GatewayServer\CAP"
$RAPPath="RDS:\GatewayServer\RAP"
$MCGPath="RDS:\GatewayServer\GatewayManagedComputerGroups"
#=============Script=============#
# Add the certificate to RDS
Set-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint" -Value $Certificate.Thumbprint
$ADGroup=[System.DirectoryServices.DirectorySearcher]::new("(&(objectCategory=Group)(samAccountName=$GroupName))").FindOne()
if ($ADGroup -ne $null) {
$ADGroup=$ADGroup.GetDirectoryEntry()
$Parent=[System.DirectoryServices.DirectoryEntry]::new($ADGroup.Parent)
$Parent.Children.Remove($ADGroup)
$Parent.CommitChanges()
$Parent.Close()
}
$ADGroup=[System.DirectoryServices.AccountManagement.GroupPrincipal]::new([System.DirectoryServices.AccountManagement.PrincipalContext]::new([System.DirectoryServices.AccountManagement.ContextType]::Domain),$GroupName)
$ADGroup.Description="Remote Gateway Users Group"
$ADGroup.GroupScope=[System.DirectoryServices.AccountManagement.GroupScope]::Global
$ADGroup.IsSecurityGroup=$true
$Member=[System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity([System.DirectoryServices.AccountManagement.PrincipalContext]::new([System.DirectoryServices.AccountManagement.ContextType]::Domain),"Administrator")
$ADGroup.Members.Add($Member)
$Member=[System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity([System.DirectoryServices.AccountManagement.PrincipalContext]::new([System.DirectoryServices.AccountManagement.ContextType]::Domain),"admin_jeberhardt")
$ADGroup.Members.Add($Member)
$ADGroup.DisplayName=$ADGroup.SamAccountName
$ADGroup.Save()
$OU=[System.DirectoryServices.DirectoryEntry]::new("LDAP://$($ADGroup.DistinguishedName)")
$NewOU=[System.DirectoryServices.DirectoryEntry]::new("LDAP://OU=<target OU>,DC=<domain name>,DC=com")
$OU.MoveTo($NewOU)
$OU.CommitChanges()
$OU.Close()
$NewOU.Close()
# Remove existing items (must be done in the order of CAP and/or RAP first, then GatewayManagedComputerGroups
$CAPs | ForEach-Object { if (Test-Path -Path "$CAPPath\$($_.Name)") { Write-Verbose "Removing $($_.Name)"; Remove-Item -Path "$CAPPath\$($_.Name)" -Recurse } }
$RAPs | ForEach-Object { if (Test-Path -Path "$RAPPath\$($_.Name)") { Write-Verbose "Removing $($_.Name)"; Remove-Item -Path "$RAPPath\$($_.Name)" -Recurse } }
$MCGs | ForEach-Object { if (Test-Path -Path "$MCGPath\$($_.Name)") { Write-Verbose "Removing $($_.Name)"; Remove-Item -Path "$MCGPath\$($_.Name)" -Recurse } }
$MCGs | ForEach-Object { Write-Verbose "Creating $($_.Name)"; New-Item -Path $MCGPath -Name $_.Name -Description $_.Desc -Computers $_.Computers > $null }
$CAPs | ForEach-Object { Write-Verbose "Creating $($_.Name)"; New-Item -Path $CAPPath -Name $_.Name -UserGroups $_.UserGroups -AuthMethod $_.AuthMethod -Status $_.Status > $null }
$RAPs | ForEach-Object { Write-Verbose "Creating $($_.Name)"; New-Item -Path $RAPPath -Name $_.Name -UserGroups $_.UserGroups -ComputerGroup $_.ComputerGroup -ComputerGroupType $_.ComputerGroupType > $null }
# Stop redirection of Serial Ports
$CAPs | ForEach-Object { Set-Item -Path "$CAPPath\$($_.Name)\DeviceRedirection\SerialPorts" -Value 0 }
Restart-Service -Name "TSGateway"
I'm trying to create userprincipalname as combination of username and hardcoded domainname
csv file:
name,displayname,givenname,surname
dhall,Don Hall,Don,Hall
Code:
Import-csv "c:\output.csv" | ForEach-Object {new-aduser -name $_.name -UserPrincipalName ("{0}#{1}" -f $_.name,"Dev.domain.Net") -DisplayName "$($_.givenname $_.surname)" -givenName $_.givenname -surname $_.surname -path "OU=Workspaces,DC=Dev,DC=domain,DC=Net" -AccountPassword (convertto-securestring passs -asplaintext -force) -Enabled [System.Convert]::toboolean($true)) -ChangePasswordAtLogon ([system.convert]::ToBoolean($true))}
And getting:
At line:1 char:159
+ ... -f $_.name,"Dev.domain.Net") -DisplayNa
+
Unexpected token '$_' in expression or stateme
+ CategoryInfo : ParserError: (:)
+ FullyQualifiedErrorId : UnexpectedToken
Tried also -UserPrincipalName ([string]::Concat($_.name,"#dev.domain.net"))
but same error
PS C:\> $PSVersionTable.PSVersion
Major Minor Build Revision
----- ----- ----- --------
5 1 14393 1944
Windows server 2016
Not sure what's causing that error (don't have an AD controller to test against at the moment so can't validate) but in cases where I'm going to need to reuse a property multiple times I tend to assign it to a temporary variable (makes it slightly easier to write the code and don't run into issues with the pipeline variable getting updated).
Import-CSV "c:\output.csv" | ForEach-Object {
$name = $_.name
$upn = "{0}#{1}" -f $name,"dev.domain.net"
New-ADUser -Name $name -UserPrincipalName $upn #...
}
# ---------------------------------------------------------
# ScriptingGamesBeginnerEvent8_PS1.ps1
# ed wilson, msft 8/21/2009
# PS1 version of HSG-08-19-09 http://bit.ly/1d8Rww
#
# ---------------------------------------------------------
Param(
[string]$path = 'C:\',
[int]$first = 50
)# end param
# *** Function Here ***
function Get-DirSize ($path){
BEGIN {}
PROCESS{
$size = 0
$folders = #()
foreach ($file in (Get-ChildItem $path -Force -ea SilentlyContinue)) {
if ($file.PSIsContainer) {
$subfolders = #(Get-DirSize $file.FullName)
$size += $subfolders[-1].Size
$folders += $subfolders
} else {
$size += $file.Length
}
}
$object = New-Object -TypeName PSObject
$object | Add-Member -MemberType NoteProperty -Name Folder -Value (Get-Item $path).fullname
$object | Add-Member -MemberType NoteProperty -Name Size -Value $size
$folders += $object
Write-Output $folders
}
END {}
} # end function Get-DirSize
Function Get-FormattedNumber($size)
{
IF($size -ge 1GB)
{
"{0:n2}" -f ($size / 1GB) + " GigaBytes"
}
ELSEIF($size -ge 1MB)
{
"{0:n2}" -f ($size / 1MB) + " MegaBytes"
}
ELSE
{
"{0:n2}" -f ($size / 1KB) + " KiloBytes"
}
} #end function Get-FormattedNumber
# *** Entry Point to Script ***
if(-not(Test-Path -Path $path))
{
Write-Host -ForegroundColor red "Unable to locate $path"
Help $MyInvocation.InvocationName -full
exit
}
Get-DirSize -path $path |
Sort-Object -Property size -Descending |
Select-Object -Property folder, size -First $first |
Format-Table -Property Folder,
#{ Label="Size of Folder" ; Expression = {Get-FormattedNumber($_.size)} }
So I have this script which I got from
http://gallery.technet.microsoft.com/scriptcenter/36bf0988-867f-45be-92c0-f9b24bd766fb#content
I've been playing around with it and created a batch file to help handle the log output of this file and such. However, I'm noticing that paths with spaces in them don't get read. For example ..Documents\My Music
Get-Item : Could not find item C:\Users\MyUser\Documents\My Music.
At C:\test.ps1:32 char:80
+ $object | Add-Member -MemberType NoteProperty -Name Folder -Value (Get-It
em <<<< $path).fullname
+ CategoryInfo : ObjectNotFound: (C:\Users\MyUser\Documents\My
Music:String) [Get-Item], IOException
+ FullyQualifiedErrorId : ItemNotFound,Microsoft.PowerShell.Commands.GetIt
emCommand
On the TechNet page for the code, someone brings the issue up but no solution is given. I'm not sure how to fix it here. I've played with the $path argument, surrounding it in " " or ' ' and such.
Here is part of the batch file to execute it:
C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -noe -command "& 'C:\test.ps1' -path "'C:\Users\MyUser\'""
Might be a bit late for answer here, but, as Aaron mentioned, this is not due to spaces in the path.
If you read the documentation for Get-Item cmdlet, there is a -Force switch, which allows the cmdlet to get items that cannot otherwise be accessed, such as hidden items.
Moreover, it seems from your code that you are not expecting to pass a wildcard pattern to the cmdlet, so instead of (Get-Item $path).FullName you should use
(Get-Item -force -LiteralPath $path).FullName
That should resolve this issue.
It's not the spaces in the path. If it was, the error would say path C:\Users\MyUser\Documents\My couldn't be found. Get-ChildItem and Get-Item behave... strangely... with certain files/directories, returning errors like you're seeing. That's why Get-ChildItem has an -ErrorAction SilentlyContinue parameter on it. I would add the same to the call to Get-Item, i.e. change
(Get-Item $path).FullName
to
(Get-Item $path -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName
or even forgo the call to Get-Item completely:
$path
As suggested by TheTrowser in a comment above: The problem may be resolved if you replace the double-quotes with single quotes surrounding the file directory with spaces. This is what solved it for me.
Using the command below didn't work for me.
get-item 'some path with two spaces.txt'
Enclosing the filename in double quotes within the single quotes, forces Powershell to use the filename as written.
get-item '"some path with two spaces.txt"'
Note: I'm totally cringing at my origal message (cleaned up a bit above). Below is a better example of what I was seeing.
$exampleA = "c:\temp\weird path\blah.txt"
$exampleB = "c:\temp\normal path\blah.txt"
# Works
get-item '$exampleA'
get-item $exampleB
# Fails
get-item $exampleA
I'm new to PowerShell and I can't seem to find how to fix this after countless Google searches. I know it's probably easy, but here's basically what I want to do and the error that shows:
PS C:\Windows\system32> $path = "HKLM:\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}"
Get-Childitem $path -ErrorAction SilentlyContinue | Foreach {
$key = Get-Item $_.PSPath
if($key.Property -eq "VMnet") {
New-ItemProperty $key -name "*NdisDeviceType" -value "1"
}
}
New-ItemProperty : Cannot find path 'C:\Windows\system32\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0014' because it does not exist.
At line:7 char:25
+ New-ItemProperty <<<< $key -name "*NdisDeviceType" -value "1"
+ CategoryInfo : ObjectNotFound: (C:\Windows\syst...02BE10318}\0014:String) [New-ItemProperty], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.NewItemPropertyCommand
New-ItemProperty : Cannot find path 'C:\Windows\system32\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}\0015' because it does not exist.
At line:7 char:25
+ New-ItemProperty <<<< $key -name "*NdisDeviceType" -value "1"
+ CategoryInfo : ObjectNotFound: (C:\Windows\syst...02BE10318}\0015:String) [New-ItemProperty], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.NewItemPropertyCommand
I clearly understand the error, it's obvious. But I don't know the proper way/command to fix it...
Try this:
$path = "HKLM:\SYSTEM\CurrentControlSet\Control\Class\" +
"{4D36E972-E325-11CE-BFC1-08002BE10318}"
Get-Childitem $path -ErrorAction SilentlyContinue |
Where {(Get-ItemProperty $_.PSPath DriverDesc) -match 'VMnet' } |
Foreach {
New-ItemProperty $_.PSPath -name "*NdisDeviceType" -value "1"
}
}
BTW I don't see any regkeys for values named "Property" perhaps you could match on the DriverDesc reg value? Anyway, the reason you're getting the error is you have to specify the PSPath to New-ItemProperty ie in your script $key.PSPath.