AMoRPH.US: PowerShell Consulting -
PowerShell MVP Don Jones has a new article about the growing need for PowerShell consultants - PowerShell experts to help IT departments automate using PowerShell.
In the past few weeks, I’ve heard from a dozen or more organizations that are starting internal projects to automate specific tasks…
(Source: ihunger)
I had a scenario where we made some Active Directory changes via the Quest Get-QADUser command we wanted reversed because it didn’t act the way we thought it would. We wanted to set the passwordNeverExpires tag on a few accounts, so we kicked around the info in THIS post.
Essentially, we grabbed a bunch of users from the output screen that we needed to put back that looked like this:
ExchSVC user CN=ExchSVC,OU=Service Accounts,DC=WEBSIE,DC=LOCAL
Guest user CN=Guest,CN=Users,DC=WEBSITE,DC=LOCAL
jason user CN=jason,CN=Users,DC=WEBSITE,DC=LOCAL
So here are a few ways of making magic with the Split command in Powershell:
#The [regex] expression “,*..=” says find a pattern that #matches zero or more commas any two characters and an equal sign. #This would match any of the following: cn= ,ou= ,dc=
$dumped = gc "dumped.txt"
foreach($user in $dumped)
{
($user -split ",*..=")[1] | out-file justSamAccount.txt -append
}
ii justsamaccount.txt
#or could split on just grabbing first line (notice the double spaces on the split #as some usernames have spaces and you don’t want to split on them
$dumped = gc "dumped.txt"
foreach($user in $dumped)
{
($user -split " ")[0] | out-file justSamAccount2.txt -append
}
ii justsamaccount2.txt
#could also use split another way and split on commas and equals signs and grab the line in question:
$dumped = gc "dumped.txt"
foreach($user in $dumped)
{
$user.split(",=")[1] | out-file justSamAccount3.txt -append
}
ii justsamaccount3.txt
and I’m certain there are plenty more, but these are the ones I came up with to fix it.
We ran this to reset some password expiry issues:
Import-Csv "Test.csv" | foreach {Get-QADUser -SamAccountName $_.SamAccountName | Set-QADUser -passwordNeverExpires $true}
but got nowhere and it didn’t change anything so I modded it to this thinking it’d just grab the user and change it:
Import-Csv "Test.csv" | foreach {Get-QADUser | Set-QADUser -passwordNeverExpires $true}
…but contrary to popular belief, the pipe just skipped passed and got the content from import-csv, but then changed EVERY user in the Get-QADUser command instead of just the ones asked… Weird, right? So we stopped it about 50 users in and copied the data to a text file to change back after we fixed the command like this:
$users=get-content test.csv
foreach ($user in $users) { Set-QADUser $user -UserMustChangePassword $true }
To fix the stuff we broke earlier, we used the Split() command as seen HERE.
Yea, it’s weird - I was just messing around in a virtual environment I stood up and was going to try to move FSMO roles with Powershell. The first thing to do was to make sure ADWS was installed as the command I needed was in that module.
ipmo activedirectory
Contrary to popular belief, that just gives me:
I can’t imagine I’m the only person to ever see this, but Google apparently thinks so:
I ended up transferring them the old fashioned way, so not sure why it didn’t install, but will keep a closer eye on it next time to see if I clicked something else wrong along the way…
UPDATE: I thought i’d check if it was the HPC version and just like that, there’s my answer: http://social.microsoft.com/Forums/is/windowshpcitpros/thread/d88d6cb9-3aa6-4af5-932b-b62854e9e9de
So I installed the new fancy PowershellASP v3 today from nSoftware.com to try out querying AD from a webpage, and with Win2008R2 you get the activedirectory cmdlets in Windows, so this will work (just a mod of the get-tweet sample code they’ve got, it’s not clean, but for testing purposes…)
<%
function Get-ldap {
import-module activedirectory
$query = $request['query'];
if ($query -eq $null) { $query = "ASMITH" };
get-aduser $query -properties *
}
$finduser = Get-ldap;
%>
<%
$finduser
%>
and it gives me this result (and some more, but for the sake of showing):
Query: AccountExpirationDate : accountExpires : 9223372036854775807 AccountLockoutTime : AccountNotDelegated : False adminCount : 1 AllowReversiblePasswordEncryption : False BadLogonCount : 0 badPasswordTime : 0 badPwdCount : 0 CannotChangePassword : False CanonicalName : AWEBSITE.local/Users/ASMITH Certificates : {} City : CN : ASMITH codePage : 0 Company : Country : countryCode : 0 Created : 12/22/2011 6:55:46 PM createTimeStamp : 12/22/2011 6:55:46 PM……….
However, in my production environment I’m not up to Win2008R2, so I’m filling in with the Quest ActiveRoles Cmdlets. They do the same thing, but apparently not with PowershellASPV3 as this doesn’t work:
<%
function Get-ldap {
add-pssnapin quest.activeroles.admanagement
$query = $request['query'];
if ($query -eq $null) { $query = "ASMITH" };
get-qaduser $query
}
$finduser = Get-ldap;
%>
<%
$finduser
%>
Super frustrating though and about to hang up the cleats. It gives me this error when run:
Enter a NT LOGIN name and get the LDAP attribs of that user. The template shows the use of the $request object to retrieve submitted form variables.
Query:
Get-QADUser : Object reference not set to an instance of an object. At line:23 char:13 + get-qaduser «« $query -properties * + CategoryInfo : NotSpecified: (:) [Get-QADUser], NullReferenceEx ception + FullyQualifiedErrorId : System.NullReferenceException,Quest.ActiveRoles. ArsPowerShellSnapIn.Powershell.Cmdlets.GetUserCmdlet
What gives here? What am I missing?
Searching Outlook with PowerShell « zeladinet -
Still trying to find a good way to use P$ as my search provider. I know everything else is usually indexed, but would be a fun project…
Wouldn’t mind seeing it in action somewhere. Got any examples of how you’ve used it?
From PowerShell MVP Don Jones
Remember my PowerShell Proverb: Every time you write a script that outputs text, God kills a puppy. It’s on your head.
WOW! At least he tells you how to avoid this fate.
So this opportunity came up with this scenario:
So we brainstormed a couple ideas and I just put this one together to monitor a mailbox that’d force log-off anyone on that box based on the computer name entered in the subject line.
#notes
#this program will receive an email and log off the machine name in the subject line
#save the subject line and run the command based on it to shutdown/log off user on box
#(Get-WmiObject -Class Win32_OperatingSystem -ComputerName .).InvokeMethod("Win32Shutdown",4)
#http://lantoolbox.com/news/shutdown-power-off-or-reboot-remote-computer-from-powershell/
#force it to match the desktop (can't reboot servers and ONLY retail POS machines somehow
#in the naming convention, or OU maybe?
#only allow if the from address is a certain address and can't be spoofed address
#check headers maybe to make sure it came from a valid address?
$olFolderInbox = 6
$outlook = new-object -com outlook.application;
$ns = $outlook.GetNameSpace("MAPI");
$inbox = $ns.GetDefaultFolder($olFolderInbox)
$inbox.items | foreach {
if($_.subject -like "*WHATEVERFILTERYOUWANTTOKEYOFF*") {(Get-WmiObject -Class Win32_OperatingSystem -ComputerName $_.subject).InvokeMethod("Win32Shutdown",4)}
}
write-host "sleeping for 30 seconds to clean out the mailbox"
sleep 30
#Name of folder to access. You can specify subfolders by using FolderName\Subfolder
$folderPath = "inbox"
#Filter older than 30 seconds
$olderThan = (get-date).Addseconds(-30)
#Set format of date to use
$dateFormat = "g" # This will base on time to do just date choose "M/dd/yyyy"
#Create filter
$sFilter = "[LastModificationTime] < `'$($olderThan.tostring($dateFormat))`'"
$outlook = New-Object -ComObject Outlook.Application
$olFolderInbox=6
$n = $outlook.GetNamespace("MAPI")
$f = $n.GetDefaultFolder($olFolderInbox)
$mailbox = $n.Folders.Item($f.Parent.Name)
$folders = $mailbox.Folders
#Navigate to the proper folder
foreach ($folderName in $folderPath.split("\"))
{
$folder = $folders.Item($folderName)
$folders = $folder.Folders
}
$Items=$folder.items
$FilteredItems = $Items.Restrict($sFilter)
for ($i = $FilteredItems.Count; $i -gt 0; $i--) {
Write-Host "Moving this out of Inbox: $($FilteredItems.Item($i).Subject)"
$FilteredItems.Item($i).Delete()
}
#Clean out any open connections
$outlook = $n = $f = $mailbox = $folder = $folders = $Items = $FilteredItems = $null;
NOTE: make sure you have Powershell V2.0 for this on all the machines you want to reboot or the “invokeMethod” command won’t enjoy you. Download it here: http://support.microsoft.com/kb/968929
function Send-Email
{
param($to, $from, $subject, $body, $smtpServer)
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = $from
$msg.To.Add($to)
$msg.Subject = $subject
$msg.Body = $body
$smtp.Send($msg)}
Or use the new fancy send-mailmessage:
send-mailmessage -to "andy@AWEBSITEcom" -subject "The script took $timer3 to run" -body "
-----stats------
Script started at: $timer1
Script finished at: $timer2
It took $timer3 to finish." -smtpserver "MAILSERVERRELAYNAME" -from "AutoScripter@AWEBSITE.com"