I am trying to create a site map with a PowerShell command from this example:
http://blogs.msdn.com/b/opal/archive/2010/04/13/generate-sharepoint-2010-sitemap-with-windows-powershell.aspx
My actions: I copied the code into a file named New-SPSiteMap
I opened the PowerShell and wrote
New-SPSiteMap –Url http://centerportal –SavePath C:\inetpub\wwwroot\wss\VirtualDirectories\80\sitemap.xml
The error I get is:
The term 'New-SPSiteMap' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the name,
or if a path was included, verify that the path is correct and try again.
At line:1 char:14
+ New-SPSiteMap <<<< -Url http://mossdev2010 -SavePath C:\inetpub\wwwroot\wss\VirtualDirectories\80\sitemap.xml
+ CategoryInfo : ObjectNotFound: (New-SPSiteMap:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
In order to have the New-SPSiteMap function available you have to execute the script containing the function:
& .\New-SPSiteMap.ps1
New-SPSiteMap –Url http://centerportal –SavePath C:\inetpub\wwwroot\wss\VirtualDirectories\80\sitemap.xml
Alliteratively, you could turn the PowerShell script into a "function" that is callable like this:
.\New-SPSiteMap.ps1 -Url http://centerportal –SavePath C:\inetpub\wwwroot\wss\VirtualDirectories\80\sitemap.xml
All you have to do is remove the function declaration function New-SPSiteMap:
param($SavePath="C:\inetpub\wwwroot\wss\VirtualDirectories\80\SiteMap.xml", $Url="http://sharepoint")
function New-Xml
{
param($RootTag="urlset",$ItemTag="url", $ChildItems="*", $SavePath="C:\SiteMap.xml")
Begin {
$xml="<?xml version=""1.0"" encoding=""UTF-8""?>
<urlset xmlns=""http://www.sitemaps.org/schemas/sitemap/0.9"">"
}
Process {
$xml += " <$ItemTag>"
foreach ($child in $_){
$Name = $child
$xml += " <$ChildItems>$url/$child</$ChildItems>"
}
$xml += " </$ItemTag>"
}
End {
$xml += "</$RootTag>"
$xmltext=[xml]$xml
$xmltext.Save($SavePath)
}
}
$web = Get-SPWeb $url
$list = $web.Lists | ForEach-Object -Process {$_.Items} | ForEach-Object -Process {$_.url.Replace(" ","%20")}
# excludes directories you don’t want in sitemap. you can put multiple lines here:
$list = $list | ? {$_ -notmatch "_catalogs"}
$list = $list | ? {$_ -notmatch "Reporting%20Templates"}
$list = $list | ? {$_ -notmatch "Reporting%20Metadata"}
$list | New-Xml -RootTag urlset -ItemTag url -ChildItems loc -SavePath $SavePath
Related
foreach ( $newfile in $file )
{
$b = Get-CMDeploymentStatus -PackageId $newfile -StatusType Any | select PackageID
Write-Output $b | Export-Csv -Path "C:\Users\PSM-6A1A000000000000\Documents\list.csv"
}
I am giving input to this with an input file which has number of package names listed and then I want to process it in such a way that the output comes one after the other right now I am getting an error as
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null. At line:16 char:20 + Write-Output $b | Export-Csv -Path "C:\Users\PSM-6A1A000000000000\Documents\lis ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCsvCommand
Your code is assuming that you will have a result coming back from $b, if it does not though, you'll get an error because you're piping $b, which is null, into Export-CSV.
$null |export-csv c:\temp\1.csv
Export-Csv : Cannot bind argument to parameter 'InputObject' because it is null.
At line:1 char:8
+ $null |export-csv c:\temp\1.csv
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Export-Csv], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ExportCs
You should add a 'Guard Clause' before you try to export.
if ($null -ne $b){
Export-csv -Append -InputObject $b
}
At least this will continue executing. Now your next problem is to determine why $b would be empty...from my experience with CM, I bet you need to specify which property in your $file you need. Maybe that line should read:
$b = Get-CMDeploymentStatus -PackageId $newfile.PackageId -StatusType Any | select PackageID
Since you say "I am giving input to this with an input file which has number of package names listed", but your code uses PackageId..
It looks to me that this file contains a packageId, each on a single line.
Anyway, I don't see the code ever reading this file..
If my assumption about the text file is correct, try:
# read the content of the text file and loop through the lines
# collect the output from Get-CMDeploymentStatus in variable $result
$result = Get-Content -Path 'X:\TheFileWithPackageIds.txt' | ForEach-Object {
# inside the ForEach-Object, the $_ automatic variable represents a single line from the text file
Get-CMDeploymentStatus -PackageId $_ -StatusType Any | select PackageID
}
# output on screen
$result
# write to new CSV file
$result | Export-Csv -Path "C:\Users\PSM-6A1A000000000000\Documents\list.csv" -NoTypeInformation
I am trying to take a list of strings separated by a return and split them by the = symbol, both sides match a registry key which is queried by Get-Item. The first half always matches fine, but referencing the second half only matches for the last item in the list:
First half example:
[string[]]$Patch = (".accda=Access.ACCDAExtension.16
.accdb=Access.Application.16" -split "`n")
Foreach ($a in $Patch) {
$RegKey = ($a -split "=")[0]
$Result = Get-Item -Path "Registry::HKEY_CLASSES_ROOT\$RegKey"
echo $Result
}
This returns:
Name Property
---- --------
.accda (default) : Access.ACCDAExtension.16
Content Type : application/msaccess.addin
.accdb (default) : Access.Application.16
Content Type : application/msaccess
Second half example:
[string[]]$Patch = ("
.accda=Access.ACCDAExtension.16
.accdb=Access.Application.16
" -split "`n")
Foreach ($a in $Patch) {
$RegKey = ($a -split "=")[1]
$Result = Get-Item -Path "Registry::HKEY_CLASSES_ROOT\$RegKey"
}
This returns:
Get-Item : Cannot find path 'HKEY_CLASSES_ROOT\Access.ACCDAExtension.16' because it does not exist.
At line:6 char:15
+ $Result = Get-Item -Path "Registry::HKEY_CLASSES_ROOT\$RegKey"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (HKEY_CLASSES_RO...DAExtension.16:String) [Get-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand
Hive: HKEY_CLASSES_ROOT
Name Property
---- --------
Access.Application.16 (default) : Microsoft Access Database
However, that registry key does exist and if I run the command manually it finds it:
get-item Registry::HKEY_CLASSES_ROOT\Access.ACCDAExtension.16
Hive: HKEY_CLASSES_ROOT
Name Property
---- --------
Access.ACCDAExtension.16 (default) : Microsoft Access Add-in
I'm pretty sure it's caused by the return at the end of each line.
PowerShell version 5.1
I have resolved this my making my list a list of strings:
[string[]]$Patch = (".accda=Access.ACCDAExtension.16",
".accdb=Access.Application.16" -split "`n")
Foreach ($a in $Patch) {
$RegKey = ($a -split "=")[1]
$Result = Get-Item -Path "Registry::HKEY_CLASSES_ROOT\$RegKey"
}
The issue was probably caused by the return at the end of each line, maybe I could have also filtered it out of the command.
Change this:
[string[]]$Patch = ("
.accda=Access.ACCDAExtension.16
.accdb=Access.Application.16
" -split "`n")
to this
[string[]]$Patch = (-split "
.accda=Access.ACCDAExtension.16
.accdb=Access.Application.16
")
That way you don't have any whitespaces.
Here is some more background on the split operator
Below powershell code is for exporting the complete registry hive to CSV file. But it gives error for exporting REG_Binary type data whose value is big as shown in the attached registry screenshot. Though I tried to convert it to string but no luck. Please suggest on how to fetch the REG_Binary data or how to convert it to string.
Function Get_Reg_Keys ($reg_key) {
$actualKey = Get-Item -Path Registry::$reg_key
#Write-Host $actualKey
ForEach ($name in $actualKey.GetValueNames()) {
# Write-Host $name
$name.Property | foreach {
$type = $actualKey.GetValue($name).GetType()
#Write-Host $type
Write-Host $actualKey.Name " | " $name " | " $actualKey.GetValue($name) " | " $type
If ( $type -eq [System.Byte[]] -Or $type -eq [System.Int64[]]) {
$a = [System.BitConverter]::ToString($actualKey.GetValue($name))
( '"{0:0}","{1:0}", "{2:0}"' -f $actualKey.Name, $name, $a) |
Out-File "C:\Temp\Automation\HKCU.csv" -append -Encoding ascii -erroraction SilentlyContinue
}
Else {
( '"{0:0}","{1:0}", "{2:0}"' -f $actualKey.Name, $name, $actualKey.GetValue($name)) |
Out-File "C:\Temp\Automation\HKCU.csv" -append -Encoding ascii -erroraction SilentlyContinue
}
}
}
$keyinfo = Get-ChildItem Registry::$reg_key
if ($keyinfo.count -gt 0) {
ForEach ($keyitem in $keyinfo) { Get_Reg_Keys ($keyitem) }
}
}
Then running: Get_Reg_Keys ("HKEY_CURRENT_USER\")
Gives the error:
Cannot convert argument "index", with value: "MRUListEx", for "GetValue" to type "System.Int64": "Cannot convert value "MRUListEx" to type "System.Int64". Error: "Input string was
not in a correct format.""
At C:\Temp\Automation\HKCUregistrynew.ps1:27 char:21
+ ( '"{0:0}","{1:0}", "{2:0}"' -f $actualKey.Name, $name, $act ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
Registry Key details:
To be honest, I'm having a tough time following your function. I'm not even sure how you're iterating over values in a key with that $name.properties | foreach... loop.
But, generally, this is pretty straight forward. For example, I've got a registry key HKCU:\Environment. I've created a property in that key named "thing", and I've stuffed it with some random binary data.
I'll take the guts of that property and output it to a file:
$reg_key = 'HKCU:\Environment'
$key_properties = Get-Item -Path $reg_key
[System.BitConverter]::ToString($key_properties.GetValue('thing')) | Out-File -FilePath .\Test.txt
cat .\Test.txt
Just to show there is nothing up my sleeve:
Good luck.
After making below changes I am able to export a registry hive to CSV file:
$actualKey = Get-Item -LiteralPath Registry::$reg_key
$keyinfo = Get-ChildItem -LiteralPath Registry::$reg_key
I was editing my powershell script and it suddenly started to give me strange errors:
-replace : The term '-replace' is not recognized as the name of a cmdlet, function, script file, or operable program
and
-Get-TfsItemHistory : The term 'Get-TfsItemHistory' is not recognized as the name of a cmdlet, function, script file, or operable program
I would understand the second error, but -replace? Thats strange.
Get-TfsItemHistory is used in referenced file VersionsCache.ps1
Script.ps1:
#For all projects, that has been changed since last build updates [AssemblyVersion], [AssemblyFileVersion], and [AssemblyInformationalVersion], attributes in all assemblyinfo.cs files.
$rootDir = "C:\Projects\UI\Evis\Dev"
$version = "2.0.0"
$buildType = "beta"
$currentChangeset = 1789
$versionsCacheFile ="C:\Projects\UI\Evis\versionsCache.txt"
. "$rootDir\VersionsCache.ps1"
$projects = Get-ChildItem "$rootDir\*.csproj" -Recurse;
function UpdateAssemblyInfo{
Param ([string]$dir, [string]$assemblyVersion, [string]$assemblyInformationalVersion)
$assemblyVersionPattern = 'AssemblyVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)'
$assemblyFileVersionPattern = 'AssemblyFileVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)'
$assemblyInformationalVersionPattern = 'AssemblyInformationalVersion\(.*\)'
$newVersion = 'AssemblyVersion("' + $assemblyVersion + '")';
$newFileVersion = 'AssemblyFileVersion("' + $assemblyVersion + '")';
$newInformationalVersion = 'AssemblyInformationalVersion("' + $assemblyInformationalVersion + '")';
$assemblyInfoFile = Get-ChildItem $dir -Filter assemblyinfo.cs -Recurse -Depth 1
$assemblyInfoContent = (Get-Content $assemblyInfoFile.FullName)
-replace $assemblyVersionPattern, $newVersion
-replace $assemblyFileVersionPattern, $newVersion
if ($assemblyInfoContent -match $assemblyInformationalVersionPattern)
{
$assemblyInfoContent = $assemblyInfoContent -replace $assemblyInformationalVersionPattern, $newInformationalVersion
}
else{
$assemblyInfoContent = $assemblyInfoContent + "`r`n[assembly: $newInformationalVersion]"
}
$assemblyInfoContent| Out-File $assemblyInfoFile.FullName
}
$publishedChangesetsCache = Load-Versions $versionsCacheFile
foreach ($project in $projects)
{
$projectDir = $project.Directory.FullName;
$assemblyInfo = Get-ChildItem $projectDir -Filter assemblyinfo.cs -Recurse -Depth 1 | select -First 1
Write-Host $projectDir -NoNewLine
$publishedChangesets = GetpublishedChangesets -dir $projectDir -publishedChangesetsCache $publishedChangesetsCache
$latestChangesetId = GetLatestChangeset $dir
Write-Host "changeset: $latestChangesetId"
if (IsChangedSinceLastBuild $latestChangesetId $publishedChangesets){
$publishedChangesets.Insert(0,$currentChangeset)
}
$changesetToPublish = $publishedChangesets[0]
$informationalVersion = "$version.$changesetToPublish"
if ($buildType -ne ""){
$informationalVersion = "$version-$buildType$changesetToPublish"
}
UpdateAssemblyInfo $projectDir -assemblyVersion "$version.$changesetToPublish" -assemblyInformationalVersion $informationalVersion
}
Save-Versions $publishedChangesetsCache -file versionsCacheFile
I guess I have some syntactic error, because it worked yesterday, but I can't figure out where.
You need to add backticks if you want to put the -replace statement in a new line:
$assemblyInfoContent = (Get-Content $assemblyInfoFile.FullName) `
-replace $assemblyVersionPattern, $newVersion `
-replace $assemblyFileVersionPattern, $newVersion
Or just write it in one line...
i have a strange problem...
i have the following code, which takes the output from Sysinternals Disk Usage tool (link below)
Disk Usage - Sys Internals
so first i get the physical drives into array $Disks, then i enumerate these through the foreach and mess about with them.
my problem lies in this line $Dir = du.exe -q -v $d.DeviceID
$PC = get-content env:COMPUTERNAME
$Disk = gwmi win32_logicaldisk -filter "drivetype=3"
foreach ($d in $Disk)
{
$Dir = du.exe -q -v $d.DeviceID
$Dir[8..($Dir.length-8)] | foreach {
$Size = $_.substring(0,10).replace(",","")/1024
$Path = $_.substring(10)
}
}
$d.DeviceID should be the drive letter (i.e. C:)
then i populate $Dir with the output from DU.exe, but $d.DeviceID is not acting how it is supposed to, running this from a task has this following result (added a line that says $d.DeviceID, to show the output):
B:
Cannot index into a null array.
At C:\DU.ps1:25 char:6
+ $Dir[ <<<< 8..($Dir.length-8)] | foreach {
+ CategoryInfo : InvalidOperation: (System.Object[]:Object[]) [],
RuntimeException
+ FullyQualifiedErrorId : NullArray
C:
Cannot index into a null array.
At C:\DU.ps1:25 char:6
+ $Dir[ <<<< 8..($Dir.length-8)] | foreach {
+ CategoryInfo : InvalidOperation: (System.Object[]:Object[]) [],
RuntimeException
+ FullyQualifiedErrorId : NullArray
D:
Cannot index into a null array.
At C:\DU.ps1:25 char:6
+ $Dir[ <<<< 8..($Dir.length-8)] | foreach {
+ CategoryInfo : InvalidOperation: (System.Object[]:Object[]) [],
RuntimeException
+ FullyQualifiedErrorId : NullArray
running it from the ISE or just from the Shell has no issues, running it on other servers from all methods works.
i do believe the population of the $Dir vairable is the problem, as the du.exe has trouble with the $d.DeviceID
i dont understand why it is just this server/task sheduler that has the issue. i have tried the following:
redefined the array element to $i = $d.deviceID to fix it down - nothing
exported the job from other server (both DCs) an imported - nothing
restarted the winmgmt service - nothing
i think its a permissions issue, but im running this on an AD as THE Dom Admin with top privilages.
please can you guys help on this one, really am stuck...
cheers
Lee
Yet another update based on comment below:
Try:
$cmd = "du.exe `-q `-v $($d.DeviceID)"
$dir = Invoke-Expression $cmd
Updating as per the comment below.
Take this example. This can get the size of every folder and display size and full path to the folder.
Function Get-FolderSize {
Param ($folderPath)
$colItems = (Get-ChildItem $folderPath -recurse | Measure-Object -property length -sum)
return $colItems.sum/1MB
}
$folders = Get-ChildItem -Recurse C:\Scripts
$folders | % {
if ($_.PSIsContainer) {
$size = Get-FolderSize $_.FullName
Write-Host $size
Write-Host $_.FullName
}
}
You can use WMI to get the drive letter and pass it to the script. For example:
$disks = gwmi win32_logicaldisk -filter "drivetype=3"
$disks | % {
$items = Get-ChildItem -Recurse $_.DeviceID -Force
$items | % {
if ($_.PSIsContainer) {
$size = Get-FolderSize $_.FullName
Write-Host $size
Write-Host $_.FullName
}
}
}
So, with this, you dont need DU.exe. You can run this as a script.
--------------OLD ANSWER _-------------------
First thing I would suspect is the path to DU.exe. What is the working directory set on the scheduled task? Is it the place where DU.exe is available?
BTW, what is the goal of this script? Are you just looking at the disk drive size? What are you capturing into $path? I did not have the patience to test your code. But, I feel that this can be easily achieved using just WMI and no other external tools.