I am trying to add 400 computer to a collection and I have an error running the powershell in SCCM. I try to change the . to _ but also encounter the same error.
Method invocation failed because [System.Char] does not contain a method named 'Split'.
At line:8 char:5
+ $collectionname = $filenames.Name[$x].Split(".")[0]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Powershell:
#Set path to collection directory
$collectiondir = "D:\Collections\"
#Pull only .TXT files into array
$filenames = Get-ChildItem $collectiondir* -include *.txt
for ($x=0; $x -lt ($filenames.Length); $x++) {
$collectionname = $filenames.Name[$x].Split(".")[0]
$collectionname
#Add new collection based on the file name
try {
New-CMDeviceCollection -Name $collectionname -LimitingCollectionName "All Systems"
}
catch {
"Error creating collection - collection may already exist: $collectionname" | Out-File "$collectiondir\$collectionname`_invalid.log" -Append
}
#Read list of computers from the text file
$computers = Get-Content $filenames[$x]
foreach($computer in $computers) {
try {
Add-CMDeviceCollectionDirectMembershipRule -CollectionName $collectionname -ResourceId $(get-cmdevice -Name $computer).ResourceID
}
catch {
"Invalid client or direct membership rule may already exist: $computer" | Out-File "$collectiondir\$collectionname`_invalid.log" -Append
}
}
}
You must have made a mistake following my hints, both do work:
$collectiondir = "D:\Collections\"
#Pull only .TXT files into array
$filenames = Get-ChildItem -Path $collectiondir -Filter *.txt
for ($x=0; $x -lt ($filenames.Length); $x++) {
$collectionname = $filenames[$x].Name.Split(".")[0]
$collectionname
}
"-----"
ForEach ($file in $filenames){
$collectionname = $file.Name.Split(".")[0]
$collectionname
}
If you wanted to split the extension a better way is to simply use BaseName instead of Name
Related
I backed up printers from a Windows 10 system to XML files. I'm trying to add them using the Set-Printconfiguration CMDLET, but it seems to be not accepting variables?
I've looked everywhere but I cannot find anything saying my syntax is wrong.
#get list of printers in backup folder
$printerNames = (Get-ChildItem -Path c:\temp\printers\*.xml -Recurse | select name).name
foreach ($printer in $printerNames)
{
Set-PrintConfiguration -PrinterName $printer -PrintTicketXml c:\temp\printers\$printer
}
Here is the code I used to get the printer XML files:
$TARGETDIR = "c:\temp\printers"
if(!(Test-Path -Path $TARGETDIR )){
New-Item -ItemType directory -Path $TARGETDIR
}
# Get all the printers:
$PN = (get-printer | select name).name
# Foreach loop to create XML file for each printer configuration
Foreach ($P in $PN){
$GPC = get-printconfiguration -PrinterName $P
mkdir c:\temp\printers\$P
$GPC.PrintTicketXML | out-file C:\Temp\printers\$P.xml
# $p|select *|out-file -Path c:\temp\$p.xml -NoTypeInformation
}
edit: here is the error I'm getting:
Set-PrintConfiguration : The specified printer was not found.
At U:\PowerShell\Scripts\backup\newRestorePrinters.ps1:15 char:9
+ Set-PrintConfiguration -PrinterName $printer -PrintTicketXml ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (MSFT_PrinterConfiguration:ROOT/StandardCi...erConfiguration) [Set-PrintConfiguration], CimException
+ FullyQualifiedErrorId : HRESULT 0x80070709,Set-PrintConfiguration
edit
I added more variables to get the list of printers w/out the .XML on the end of the names. It still gives me the same error output. It looks like it's not passing my variables to the set-printconfiguration command?
New restore script code:
$printerShortNameList = (Get-ChildItem -Path c:\temp\printers\*.xml -Recurse | select name).name
foreach ($shortName in $printerShortNameList)
{
$shortName.Replace('.xml', "x")
}
#get list of printers in backup folder
$printerNames = (Get-ChildItem -Path c:\temp\printers\*.xml -Recurse | select name).name
foreach ($printer in $printerNames)
{
Set-PrintConfiguration -PrinterName $shortName -PrintTicketXml c:\temp\printers\$printer
}
What was the error message? Shouldn't you take the '.xml' off the end of $printer for the printer name? I think you have to use add-printer first. I don't believe Set-PrintConfiguration creates printers.
On the bottom when you make the xml files, why do you create the c:\temp\printers\$p directory?
Set-PrintConfiguration:
You need administrator credentials to use Set-PrintConfiguration.
I came across PowerShell script to log Microsoft Office version of remote computer on domain. I want to run it as logon script to I modified OpenRemoteBaseKey to OpenBaseKey and this is the code:
$version = 0
$reg = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine', 'Default')
$reg.OpenSubKey('software\Microsoft\Office').GetSubKeyNames() |% {
if ($_ -match '(\d+)\.') {
if ([int]$matches[1] -gt $version) {
$version = $matches[1]
}
}
}
if ($version) {
Add-Content -Path \\server\share\oversion.txt -Value "$env:computername $env:username : $version"
}
else {
Add-Content -Path \\server\share\oversion.txt -Value "$env:computername $env:username : 0"
}
but now I receive error:
You cannot call a method on a null-valued expression.
At line:4 char:1
+ $reg.OpenSubKey('software\Microsoft\Office').GetSubKeyNames() |% {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
but not sure what this means since GetSubKeyNames seems valid: https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.registrykey.getsubkeynames?view=netframework-4.7.2, also it works with OpenRemoteBaseKey, can someone point me to right direction, please?
I'm not sure why OpenRemoteBaseKey works, but OpenBaseKey doesn't because I cannot reproduce that..
You might however try the more Powershell way of doing this:
$version = 0
Get-ChildItem -Path 'HKLM:\SOFTWARE\Microsoft\Office' -Name | Where-Object {$_ -match '(\d+)\.\d+'} | ForEach-Object {
$version = [math]::Max([int]$_, $version)
}
Add-Content -Path \\server\share\oversion.txt -Value "$env:COMPUTERNAME $env:USERNAME : $version"
I have a script that I am trying to get to sort through a directory and open all the zip files and store the text files all to one directory. Here is the code:
#Script to open zip files in tree
New-Item E:\Files -type directory
Get-ChildItem -Path E:\SNL_Insurance\* -Recurse -Exclude "*.md5"|
ForEach-Object {
$file = $_
write-host $file;
$destination = "E:\Files"
$shell = New-Object -com shell.application
$zip = $shell.NameSpace($file) |
foreach($item in $_.items()){
$shell.Namespace($destination).copyhere($item)
}
}
I think I almost have it, but keep getting this error (any elaboration on piping would be helpful):
Unexpected token 'in' in expression or statement.
At E:\Expand-ZIPFile.ps1:14 char:19
+ foreach($item in <<<< $_.items()){
+ CategoryInfo : ParserError: (in:String) [], ParseException
+ FullyQualifiedErrorId : UnexpectedToken
EDIT:
Ahh... thanks for that distinction. I made your edits but after each of my "write-host" checks to see the file name I get the following error:
`You cannot call a method on a null-valued expression. At E:\Expand-ZIPFile.ps1:14 char:30 + foreach($item in $zip.items <<<< ()){ + CategoryInfo : InvalidOperation: (items:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull
EDIT2: So the original code does copy files to a new directory but also copies the whole zip file over. I tried to add an if statement to only copy files that are .txt but the code just steps through each directory without copying anything. If you have any idea that would be appreciated as I have exhausted all my ideas. Here is the code:
new-Item E:\Files -type directory
Get-Childitem -path E:\SNL_Insurance\* -recurse -exclude "*.md5" |
Foreach-object {
$file = $_
write-host $file;
$destination = "E:\Files"
$shell = new-object -com shell.application
$zip = $shell.NameSpace($file.Fullname)
foreach($item in $zip.items()){
if ($item.Extension -eq ".txt") {
$shell.Namespace($destination).copyhere($item)
}
}
}
You're confusing foreach with ForEach-Object loops. The former neither read from nor do they write to pipelines. Also, $file is a FileInfo object, not a path. The NameSpace method expects a path string, so you need to use $file.FullName.
Replace
$zip = $shell.NameSpace($file) |
foreach($item in $_.items()){
$shell.Namespace($destination).copyhere($item)
}
with
$zip = $shell.NameSpace($file.FullName)
foreach($item in $zip.items()){
$shell.Namespace($destination).copyhere($item)
}
I am trying to delete bunch of files based on a csv file. Files listed in the csv file should be deleted from the target file share. When I run the script I am in the target folder but I am getting the following error:
Remove-Item : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties
do not match any of the parameters that take pipeline input.
At line:9 char:56
+ Get-Childitem | where {$_.Name -match $filename} | Remove-Item -verbose -$fi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (gp.html:PSObject) [Remove-Item], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.RemoveItemCommand
Code below:
$csvFile = Import-csv "C:\\DeleteFiles.csv"
foreach($user in $csvFile)
{
$filename = $user.FileName
write-host $filename
Get-Childitem | where {$_.Name -match $filename} | Remove-Item -verbose -$fileName
}
According to your comment, you have some empty filenames in the csv file. This solution should be more robust:
$csvFile = Import-csv "C:\\DeleteFiles.csv"
foreach($user in $csvFile)
{
$filename = $user.FileName
write-host "The filename is '$filename'"
if (test-path $filename)
{
Remove-Item -verbose $fileName
}
else
{
Write-Host "File '$filename' not found"
}
}
I want to take a text file with usernames, and then search a specific location (UNC path) and return any matches found, outputting them to a log file:
#Searches target folder for all folders matching input
$start = (get-date -uformat "%Y-%m-%d_%H%M")
$defaultLogFileName = "folder_matcher" + $start + ".log"
#Log file header
$header = #()
$header += "=============================="
$header += "Search results"
$header += ""
$header += "Execution Start: " + (get-date -uformat "%Y-%m-%d %H%M") + ""
$header += ""
#Get the logfile location
do
{
$logdir = Read-Host "Enter log directory (or press Enter for default c:\)"
if ($logdir -eq "")
{$logfile = ("c:\" + $defaultLogFileName); break;}
if(Test-Path $logdir)
{$logfile += ($logdir + "\" + $defaultLogFileName); break;}
Write-Host -ForegroundColor Red "Directory does not exist"
} while (!(Test-Path $logfile))
$SourceFile = Read-Host "Enter file path"
$SearchValue = Read-host "Enter target directory to sweep"
$header | Out-File -FilePath $logfile
foreach($user in $sourcefile){
Get-ChildItem $SearchValue -filter $user | Out-file -Append -FilePath $logfile
}
When I attempt to use Get-ChildItem in this loop, this is the result:
Get-ChildItem : Second path fragment must not be a drive or UNC name.
Parameter name: path2
At \\erebus\erebus_users$\rraymond1\ps\searchandmatch.ps1:32 char:14
+ Get-ChildItem <<<< $SearchValue -filter $user | Out-file -Append -FilePath $logfile
+ CategoryInfo : InvalidArgument: (\\harvard\tsprofiles$:String)
[Get-ChildItem], ArgumentException + FullyQualifiedErrorId DirArgumentError,Microsoft.PowerShell.Commands.GetChildItemCommand
I have tried replacing the variables with fixed values (even mapping the UNC path locally and trying to run it that way), and the problem remains. How can I fix it?