Comment Based Help not displayed in Powershell - powershell

I am trying to implement Comment Based Help as described here with Powershell 5.1 on Windows Server 2016.
The script I am using is called blah.ps1:
<#
.DESCRIPTION
blah blah
#>
function Blahblah
{
}
In Powershell, I can load the script:
.\blah.ps1
But when I ask for help on this function using:
Get-Help Blahblah
Powershell only reports an error:
Get-Help : Get-Help could not find Blahblah in a help file in this session. To download updated help topics type: "Update-Help". To get help online, search for the help topic in the TechNet library at http://go.microsoft.com/fwlink/?LinkID=107116.
At line:1 char:1
+ Get-Help Blahblah
+ ~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [Get-Help], HelpNotFoundException
+ FullyQualifiedErrorId : HelpNotFound,Microsoft.PowerShell.Commands.GetHelpCommand
I am assuming that Get-Help can be used with the custom help comments. What am I missing?

Import the script as a module instead of running it.
Import-Module .\blah.ps1

While declaring the function, including the help immediately after the function header, saving it in a module, and importing the module is probably the best way to handle it, you can make your script's help available to Get-Help by ensuring that...
the function name and the file name match (which means one function per file), and...
ensuring that the script file is in a directory that is in $env:PATH.
The help for the function can be declared before the function itself is, provided that there is no more than one blank line between the help's closing #> and the beginning of the function declaration.
See Get-Help about_Comment_Based_Help in either the PowerShell help or the linked Microsoft documentation.

Related

Use of ConvertTo-ExcelXlsx (ImportExcel) to convert .xls to .xlsx

Trying to convert .xls file to .xlsx
by ConvertTo-ExcelXlsx function of ImportExcel module
https://github.com/dfinke/ImportExcel/
Github documentation says
Thanks to Mikkel Nordberg. He contributed a ConvertTo-ExcelXlsx. To use it, Excel needs to be installed. The function converts the older Excel file format ending in .xls to the new format ending in .xlsx.
help ConvertTo-ExcelXls returns the following as syntax:
ConvertTo-ExcelXlsx [-Path] [-Force] []
So I am trying do it like:
ConvertTo-ExcelXls -path "C:\MyFolder\MyFile.xls"
but I am getting:
ConvertTo-ExcelXls : The term 'ConvertTo-ExcelXls' 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:2 char:1
+ ConvertTo-ExcelXls -path 'C:\MyFolder\ ...
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (ConvertTo-ExcelXls:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Well the answer is basically written in your question. The syntax is ConvertTo-ExcelXlsx but you invoked ConvertTo-ExcelXls which is not available in your shell (note the missing x at the end).
So here is the thing. Powershell adds Get- if it cannot resolve a command, so if you invoke help, it's actually Get-Help. Get-Help outputs any command that matches a part of your specified name. Get-Help -Name Excel would have given you the function as well (and probably some more). That's why you got help for ConvertTo-ExcelXlsx even though you looked up ConvertTo-ExcelXls. This makes it a littly bit tricky, but on the other hand, the help message was really helpful.

Script runs in ISE but not in Powershell

I have a powershell script. This script runs perfectly fine if I open it in Powershell ISE, however, if I right click on the file and click 'run with powershell' the script throws an error.
Furthermore, I read in previous threads that the following execution pattern solved the issue for some people:
powershell -STA -File script.ps1
In this case this didn't solve the issue, however it did allow me to read the error:
At C:\Users\sancarn\AppData\Local\Temp\script.ps1:20 char:20
+ $parent = [System.Windows.Forms.TreeNode]$global:database.Ite ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unable to find type [System.Windows.Forms.TreeNode].
At C:\Users\sancarn\AppData\Local\Temp\script.ps1:27 char:36
+ ... [void]$node.nodes.add([System.Windows.Forms.TreeNode]::new(" ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unable to find type [System.Windows.Forms.TreeNode].
At C:\Users\sancarn\AppData\Local\Temp\script.ps1:33 char:45
+ ... PSCustomObject]IWDBGetChildren([System.Windows.Forms.TreeNode]$node) ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unable to find type [System.Windows.Forms.TreeNode].
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TypeNotFound
This having been said, I'm not sure I can really do anything about this error specifically... I already load System.Windows.Forms and System.Drawing... Does anyone have any idea how to execute this file properly?
Edit
Other attempts at trying to fix the issue:
powershell -NoExit -STA -File script.ps1
powershell -NoExit -STA -File script.ps1 -Scope Global
Edit 2
I have also tried adding:
Add-Type -AssemblyName System.Windows.Forms
To the top of the powershell script. The issue remains unresolved however.
Edit:
Not sure why this is being flagged as a duplicate after
this answer already has a recommended answer and
the recommended answer demonstrates why this is different.
...
As #PetSerAl said in his comment, the answer is in https://stackoverflow.com/a/34637458
Every PowerShell script is completely parsed before the first statement in the script is executed. An unresolvable type name token inside a class definition is considered a parse error. To solve your problem, you have to load your types before the class definition is parsed, so the class definition has to be in a separate file.
Ultimately to resolve the issue I need to either load my class definitions as a separate file, or store my declarations in a header file, which calls the class definitions (and the rest of the script).
I am amazed this was even an issue but it works now, so that's good...
Edit
In my case it is a bit different to the post linked by the solution author. I'm actually building a ruby library for executing Powershell on windows machines. Currently I don't write data to a file and I can't guarantee that a here-string/invoke-expression will work.
Invoke-Expression #"
$anotherString=#"
hello world!
"#
"# <--- Powershell will throw an error here!
Instead I've decided to encode the body if a header is present, and then decode and execute at runtime
require 'base64'
if header!=""
encoded_body = Base64.strict_encode64(body.encode("utf-16le"))
body = <<-END_TRANSFORMATION
#{header}
$encoded_body = "#{encoded_body}"
Invoke-Expression $([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($encoded_body)))
END_TRANSFORMATION
end
So far this has appeared to work in all cases, doesn't need external files, and will work even if users use here-doc strings in their Powershell scripts!

Powershell Get-FileMetaData not recognized

I am trying to use the PowerShell command 'Get-FileMetaData' however PowerShell ISE outputs the following error:
Get-FileMetaData : The term 'Get-FileMetaData' 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:1
+ Get-FileMetaData E:\Test_Output
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-FileMetaData:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
The path is correct, I have also tried various existing paths. I cant find anything about what version this command requires, but using $PSVersionTable.PSVersion output states 'Major 5' so I believe I am using PS v5.
Has anyone else had issue with this command? I have found various forums mentioning its function, but cant find much on troubleshooting it.
Thanks for any help!
That is not a core PowerShell cmdlet so I would expect that to fail for most people. As far as I know that comes from the Script Gallery. You need to download that first.
So if you want that to be loaded then take that module will need to be imported either manually or automatically.
You can read more about module loading on MSDN
Using the free tool 'exiftool' I have put together to following script:
$creator = C:\Windows\exiftool.exe "-Creator" $Image.FullName
This allows $creator to be the files Creator which in the case of our production images is the same as the Author.

Powershell module not loading

I am trying to load a PowerShell module that executes a custom cmdlet function but I can't get it to load... I've applied the solutions of several previous questions, but now I'm just going in circles. Here are the specs of what I have done so far and the specific error that returns. Note that as I am new to PowerShell and programming in general, it wouldn't surprise me that my problem isn't a file path issue but a logic error in my actual function:
I created a profile function for a custom cmdlet that allows me to
open project files from two different paths:
function push-project( $project )
{
pushd ~/Documents/Visual Studio 2015/Projects/$project;
pushd ~/Documents/GitHub/$project;
}
New-Alias -Name pp -Value push-project;
I created a module by saving the function as ProfileFunctions.psm1
in the following directory:
~\Documents\WindowsPowerShell\Modules\ProfileFunctions\ProfileFunctions.psm1
To invoke the function, per its syntax, I type in pp $projectName into the PS console window, but the error that returns is standard not recognized:
pp : The term 'pp' 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:1
pp MyFirstApp
~~
CategoryInfo : ObjectNotFound: (pp:String) [], CommandNotFoundException
FullyQualifiedErrorId : CommandNotFoundException
I copied and pasted your code into a Windows 8.1 machine I have here. It worked great (apart from the folder names not existing, since I don't have Visual Studio).
Things off the top of my head that might stop your module from working:
The file is actually called ProfileFunctions.psm1.ps1 or ProfileFunctions.psm1.txt or something.
The Modules folder is saved in someone else's documents folder, or the Public documents folder.
You've accidentally put a space in the folder name (it must be WindowsPowerShell, not Windows PowerShell).
I Think your problem is that the Alias pp is not exported from the module.
You either define the alias outside the module, as supposed to or explicitly export it from the module using.
Export-ModuleMember -Function pushproject -Alias pp
Find more details in this article Unable to Create a Powershell Alias in a script Module

Calling a function within module / Powershell

I must be missing something basic here, but i'm new to powershell...
I wrote a function and saved it in a file called "UserSelectionList.psm1", the function is stubbed out like this:
function Global:UserSelectionList([String[]] $UserOptions)
{
...
}
i then try to call it with this script:
Import-module "l:\support downstream\solarc\cngl\powershell scripts\userselectionlist.psm1"
$Options = "a","b","c"
cls
$result = UserSelectionList $Options
echo $result
The resulting error is:
The term 'UserSelectionList' 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:5 char:28
+ $result = UserSelectionList <<<< $Options
+ CategoryInfo : ObjectNotFound: (UserSelectionList:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I'm planning to have more than one function in a module, but this is where I'm at.
thanks in advance
I've encountered the same problem. Steps to reproduce:
Write a PowerShell script with an Import-Module statement
Execute the script at a PowerShell prompt
Add a function to the imported module
Modify the script to call the newly-added function
Execute the script again, in the same PowerShell session
The error went away after I added the -Force argument to Import-Module. The -Force argument can be removed once the function in the imported module is able to be called.
Note that latkin has alluded to this solution in his comment to the question. I'm hoping this will make it more visible.
You only need to Get-Command if you didn't export the method properly from the module.
At the end of your module put this:
Export-ModuleMember -Function UserSelectionList
Note that it also accepts wild cards, so for example if you have 5 different Get-Some-Value functions that follow a naming convention you could just do
Export-ModuleMember -Function Get-*
Side note on -Force: all that does is check if a module is already loaded and, if it is, removes it before continuing with the import. It's the same as saying:
Remove-Module userselectionlist.psm1
Import-Module userselectionlist.psm1
[Edit] I was not doing a Import Module with a -Force option. The answer below is incorrect, but perhaps the Get-Command forced a refresh? Either way, I'm leaving it for completeness of the experience!
Thanks to latkin for pushing me to another path where i found this:
How do I retrieve command from a module
Not only do you have to import a module, you then have to "get" it as well (?)
Import-Module -Name <ModuleName>
Get-Command -Module <ModuleName>
After I issued the Get-Command, everything started to work!
Thanks latkin for quick response!