2014/01/26

PowerShell Tip - Adding Help in the PARAM statement

It’s always a good idea to include help within your functions ! You never know who might benefit from it.

With PowerShell adding help to your script, function and module is a really easy thing to do.

Help in the PARAM statements


A very cool way to add some help to your script parameters is to add comments within the PARAM statement block. With this method you do not need to write a .PARAMETER directive for each paremeters. However you are required to write at least one directive in the Comment Based Help block (.SYNOPSIS or .DESCRIPTION) to be able to use it.

Example:

<#
    .SYNOPSIS
        This function will get some cool stuff
#>
    PARAM(
        # Specifies the computer name
        $ComputerName,
    
        # Specifies the Log directory Path
        $Logs = C:\lazywinadmin\logs
    )#PARAM

Then use Get-Help against your function/script

Get-Help Get-Something -Parameter *


This command will only return the Parameters information with the help we added in the PARAM statement

-ComputerName 
    Specifies the ComputerName

    Required?                    true
    Position?                    named
    Default value
    Accept pipeline input?       false
    Accept wildcard characters?  false


-Logs 
    Specifies the Log directory Path

    Required?                    false
    Position?                    named
    Default value                c:\lazywinadmin\logs
    Accept pipeline input?       false
    Accept wildcard characters?  false




Even if this tip is pretty cool, I would still recommend to use the Comment Based Help block to have a centralized place to put all the help !


Thanks for reading! If you have any questions, leave a comment or send me an email at fxcat@lazywinadmin.com. I invite you to follow me on Twitter @lazywinadm / Google+ / LinkedIn. You can also follow the LazyWinAdmin Blog on Facebook Page and Google+ Page.

32 comments:

  1. Hi Francois,

    I have run the the script in powershell with Admin Rights and with verbose. I see that it creates the html and says the mail is being sent but nothing comes trough to both email addresses stipulated. No errors are show.

    ReplyDelete
  2. Hi Dhillan,


    Which version of PowerShell are you using ?
    Does it work if you manually send an email ?


    Fx

    ReplyDelete
  3. Hi,


    I am using Pwershell Version 4 on Windows Server 2012 R2.
    I have other scripts which send emails fine and if I do a telnet send mail it works fine.

    ReplyDelete
  4. Hi Dhillan, I think I found the issue.
    I will update the script and let you know.


    Fx

    ReplyDelete
  5. I updated the script on technet.

    http://gallery.technet.microsoft.com/Report-Active-Directory-008cd9eb



    Let me know if this solved your issue.


    Thank you to let me know! Appreciated

    ReplyDelete
  6. Hi Fx


    I have run the new version, the email sending now works.
    However it only gathered the netlogon from one of my 6 DC's :(

    ReplyDelete
  7. My bad I left a line that I added for the troubleshooting.
    I updated the script, please try with the last version

    ReplyDelete
  8. Thanks works 100% :)
    Much Appreciated

    ReplyDelete
  9. Awesome!! :-)
    Please rate the script on technet if it is helpful, have a good one

    ReplyDelete
  10. Hi Francois.

    Very nice script indeed! Thank you for sharing.

    I have a question, one of the groups i'm monitoring has 100+ users so the export to csv takes a couple of minutes but i plan on scheduling this to run every 15 sec. Can I do that without problems?



    Best regards

    ReplyDelete
  11. Newbie question: How do I schedule a task to run the script with the required inputs?
    The code im running inside PS looks like this;


    "C:\Scripts\LazyWinAdmin\TOOL-MONITOR-AD_Group_20131127.ps1 -group "Domain Admins","G1","Enterprise Admins","G2","G3","G4","G5","G6" -Emailfrom xxx@mydomain.com -Emailto "xxx@otherdomain.com" -Emailserver smtp.mydomain.local"


    and it works like a charm! But I cant figure out how to schedule a task that runs the script with the inputs!
    Normally when I have schedules tasks that runs PS scripts I use a .bat file to call the script.


    Francois and others - have a great weekend!

    ReplyDelete
  12. Hi again,

    You have to escape " character by using \

    Your line should look like that:

    "C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe" -command "C:\Scripts\LazyWinAdmin\TOOL-MONITOR-AD_Group_20131127.ps1 -group \"Domain Admins\",\"G1\",\"Enterprise Admins\",\"G2\",\"G3\",\"G4\",\"G5\",\"G6\" -Emailfrom \"xxx@mydomain.com\" -Emailto \"xxx@otherdomain.com\" -Emailserver \"smtp.mydomain.local\""
    Hope this help.
    Thanks have a good week-end too

    ReplyDelete
  13. Thanks! that worked. I learned something new today :)

    ReplyDelete
  14. First off, this is fantastic, thank you for sharing.

    I am running into an issue where, if a group is a member of a group that I am scanning, I will receive a notification that the group was removed and added. It also appears to happen if there is a disabled account in the group as well. This will happen upon every scan. This may have been something that I read over and apologize ahead of time.

    Any assistance is greatly appreciated.

    ReplyDelete
  15. Thanks for your comment.


    I will try to look at this this week-end.


    FX

    ReplyDelete
  16. Thanks for the script! I noticed the emails and reports have a DisplayName column but never show anything so I modified the following lines by adding DisplayName a couple of times to get it to show.


    $Members = Get-QADGroupMember -Identity $GroupName -Indirect -ErrorAction Stop -ErrorVariable
    ErrorProcessGetQADGroupMember #| Select-Object -Property Name, SamAccountName, DN , DisplayName

    $Changes = Compare-Object -DifferenceObject $ImportCSV -ReferenceObject $Members -ErrorAction stop -ErrorVariable ErrorProcessCompareObject -Property Name,Displayname,SamAccountName,DN | Select-Object @{Name="DateTime";Expression={Get-Date -Format "yyyyMMdd-hh:mm:ss"}},@{n='State';e={IF ($_.SideIndicator -eq "=>"){"Removed"}ELSE { "Added" }}},DisplayName, SamAccountName, DN | Where-Object {$_.name -notlike "*no user or group*"}

    ReplyDelete
  17. Hi Francois,
    Thanks for the great work. I was wondering if there's a way to capture WHO (the username of the person who add/remove group members) made the change in the same report?
    Thanks,
    Steve

    ReplyDelete
  18. Hi Steve,


    Interesting, I actually got an email today from someone who retrieve this information from the Eventlogs, I will have to look at it. I believe some sort of Auditing need to be enabled for that.


    Thanks for your comment.

    ReplyDelete
  19. Thanks for your comment Jay, I will look into that.

    ReplyDelete
  20. I'm using PS 4.0 - getting tons of false positives (adds and removes that aren't happening - often seeing both adds and removes for the same user in the same report). Any ideas what I might need to change?

    ReplyDelete
  21. Is there any way to make this not report events in the netlogon.log that have already been reported, or do I need to manually clear out netlogon.log on all the DC's?

    ReplyDelete
  22. Hey StPaddy

    Hum... I would have to think about that.

    In some case, I like that fact that this is flagged again to show that this is not resolved.
    But if indeed everything is clean and well configured... might be annoying to receive those again



    Maybe Archiving the netlogon.log content could be a solution. I can add this to my list as an optional parameter.


    Thanks for your comment

    ReplyDelete
  23. Hi Jordan,


    This is really weird... I ran the script against PS 4.0 without issues.


    Permissions ? DC overloaded ?

    ReplyDelete
  24. Suggestion: It appears to only query DCs in the root of the forest you are in irrespective of the domain the machine is you are running the script from or the account you are using. It would be nice if we had the option to walk the forest and report on all domains, or maybe specify the domain via a switch.

    ReplyDelete
  25. The truth is, this is the flash guideline of having in just about any business. Most you need to do is, commit a little time inside investigation along with fully grasp the particular very popular conditions inside Forex Live contests.

    ReplyDelete
  26. Hi Francois-Xavier,

    I'm interested to know if you have you actually documented the rights needed to run this. You state that "Permission to Read \\DC\admin$, a basic account without specific rights will do it". That's not correct. Whilst we can get past that by adding our account to the Backup Operators group, only administrators can read the Netlogon.log file. It gets very tricky and I haven't completed my investigation, but you can't run this script following the principle of least privilege in its current state.



    I'm not being critical, I'm just interested to know if you've worked through this.


    Cheers,
    Jeremy

    ReplyDelete
  27. Thanks for your comment Jeremy.
    It's good to be critical! :-) We learn everyday.

    After doing some tests, indeed I do not have access to this share with a regular account.
    I can only assume something was tweaked at my previous work on this share to allow me to access it with a regular Domain User account.

    Let me know what you find, I'm curious to know.
    I guess it is time to update this script :-)

    Thanks for pointing this out, appreciated

    ReplyDelete
  28. No problems.

    To access the admin$ administrative share on Domain Controllers you must at least be in the Builtin Backup Operators domain group.

    As only Administrators have access to Netlogon.log, you need the SeBackupPriviledge in your token, as this will read the file regardless of the ACL on the file. I now have some C# code in the PowerShell script that injects that right on the fly.

    However, cmdlets like Copy-Item, Get-Item, etc, don't use the backup semantics flag, and neither does copy and xcopy, so it doesn't help. But robocopy does with the /b parameter. However, whilst robocopy will read it, it won't copy it because the file is in use. This is has always been an issue with robocopy.

    So the only way to copy this file is to write some code in C# using the CreateFile function, where you can tell it to use the backup semantics flag. I'll save this for a rainy day, as I don't have the time at the moment.

    My goal is to implement this as a scheduled task, but I refuse to implement scheduled tasks with Admin privileges.

    ReplyDelete
  29. Interesting, thanks for the information. Let me know if you find anything else

    ReplyDelete