#loopIt displays a bunch of ooooooo as a progress bar. I really wish it had the bar style like an initial windows install, but it is not a big deal.
for($it = 0; $it -lt $copy.length; $it++)
{
# Report progress
$percents = [System.Math]::Round(100 * $it / $copy.length)
Write-Progress -Activity "Working..." `
-PercentComplete $percents `
-CurrentOperation "$percents % complete" `
-Status "Please wait."
}
......
June 6, 2009
Powershell Progress Bar
I needed to show a simple progress bar while I was running a long powershell script. It turns out that it is really simple to do and a snippet is found below:
June 5, 2009
Powershell and online games
WoW (and I mean both wow and warcraft)! I have not played this game in years but I know many developers that still do. It seems we have a script for that as well! Here is a link to someone who wrote an updater script in POSh for World of Warcraft add-ons.
ServerFault
Seems the guys at StackOverflow finally made their "sister" public (was beta for a while). It can be found Here.
Send email using powershell
Sending an email in powershell is actually very easy using .NET. Here is how you would do it:
Set-PSDebug -Strict
# Create mail and set priority
$mail = new-object Net.Mail.MailMessage
$mail.Priority = [System.Net.Mail.MailPriority]::High
# Create from, to, and bcc
$mail.From = "test@test.com"
$mail.To.Add("test2@test2.com")
$mail.CC.Add("cc@test.com")
$mail.BCC.Add("bcc@test.com")
# Create the message
$mail.Subject = "Test Email from POSh" + " (" + [System.DateTime]::Now.ToString("yyyy-MM-dd HH:mm") + ")"
$mail.Body = "<b>Testing Application</b>"
$mail.IsBodyHtml = $true
# Set SMTP Server and create SMTP Client
$smtp = new-object Net.Mail.SmtpClient
$smtp.Host = "127.0.0.1"
$smtp.Port = "25"
$smtp.EnableSsl = $false
# Send message
try {
$smtp.Send($mail)
}
catch {
"Exception caught: {0}" -f $Error[0]
}
June 4, 2009
Ping servers using powershell
A simple check to see if your server is still alive and a poor admins script that can be run as a service:
#create a file that has IP's or ServerNames to check, one per line.
$file=gc "D:\HearbeatPing.txt"
foreach($ip in $file)
{
$OK=get-wmiobject win32_pingstatus -Filter "Address='$ip'" | Select-Object statuscode
if($OK.statuscode -eq 0) {
write-host $ip is UP}
else {
write-host $ip is DOWN -background "red"}
}
FTP in Powershell
Here is an easy way to FTP in powershell:
$src = "ftp://ftp.microsoft.com/Services/Museum/pictures/windows1box.jpg"To upload a file, you need to change one line:
$dest = "c:\temp\windows1box.jpg"
$Client = New-Object System.Net.WebClient
$Client.DownloadFile($src, $dest)
$Client.UploadFile($src, $dest)Oh, Windows1 was a very long time ago!
June 3, 2009
LogParser unzip and parse
All credit for this goes to Gluegood Software who saw this as a problem a few months ago and released freeware to help solve it. I was excited about this, but when I tried it I kept getting errors relating to invalid checksum. You can find Here a slightly modified version of what Gluegood did. The basic idea is the same and the files added/modified were:
.zip (always worked with original code)
.tar
.tar.bz2
.tar.gz
One last note is that the original code that gluegood wrote may work for you and I just may have been the unlucky one who had some odd gzipped files...
- UninstallDotNetAsCom.bat (added)
- Module1.vb (modified)
- Class1.vb (modified)
- Zip.vbproj (modified)
- Archive Folder added to Zip project
LogParser.exe -i:COM "select * From 'Test.tar.bz2'" -iProgId:Gluegood.LogParser.ZIP -iCOMParams:iQuery="Select * From *.txt",iInputParameters="-i:CSV -HeaderRow:Off" -o:DataGridThis additional code now gives capability for:
LogParser.exe -i:COM "select * From 'Test.tar.gz'" -iProgId:Gluegood.LogParser.ZIP -iCOMParams:iQuery="Select * From *.txt",iInputParameters="-i:CSV -HeaderRow:Off" -o:DataGrid
.zip (always worked with original code)
.tar
.tar.bz2
.tar.gz
One last note is that the original code that gluegood wrote may work for you and I just may have been the unlucky one who had some odd gzipped files...
AzMan Test Harness
I (or someone from our operations team) often needed a way to quickly test operations in my applications. This had to be done without going directly into our main application or digging into the AzMan console. I whipped up (back in '04 but still used today) this simple windows form. I have uploaded my old test harness here . This harness is very old (written in .NET 1.1), so you may have to update some code if you are putting this into 2.0 or 3.5. The windows form when run will allow you to test:
- Test either against XML or AD store
- Specify the Application Name
- Specify the OperationName
- Test with either a User SID or a UserName
Powershell Exception Helper
Powershell does not really have a good way to log and handle exceptions. You can find a bunch of articles on the Trap keyword and what can be done with it. Here is one great article on the topic. Having said that, my co-worker 'AC' did it again and created this wonderful helper file which I figured I would share with you. You can use this code inside every function at the first line. This works very well if you have many posh scripts being called:
function MyFunction($param1, $param2)
{
trap { TrackError }
....
}
$global:trackedErrorHashCode = $null
function TrackError
{
$err = $error[0]
$hashCode = $err.GetHashCode()
if($global:trackedErrorHashCode -eq $hashCode) {
return
}
else {
$global:trackedErrorHashCode = $hashCode
}
$text = BuildErrorMessage $err
WriteErrorMessage $text
SaveErrorMessage $text
throw $err
}
function BuildErrorMessage($err)
{
$text = ""
$text += FormatAsLine "Error ----------------------"
$text += FormatAsLine
$text += FormatAsLine "$($err.InvocationInfo.InvocationName): $($err)"
$text += FormatAsLine $err.InvocationInfo.PositionMessage
$text += FormatAsLine
$text += FormatAsLine "$($err.Exception.GetType().Name)"
$text += FormatAsLine
$text += FormatAsLine "StackTrace -----------------"
$text += FormatAsLine
$info = $err.InvocationInfo
$stack = Get-PSCallStack
$text += FormatCallStackLine $stack[2].command $info.ScriptName $info.ScriptLineNumber
$stack[3..$stack.length] | % {
$text += FormatCallStackLine $_.Command $_.ScriptName $_.ScriptLineNumber
}
$text += FormatAsLine "----------------------------"
$text
}
function FormatAsLine($text)
{
$text + "`n"
}
function FormatCallStackLine($command, $file, $lineNumber)
{
" At '$command' in $($file):$lineNumber`n"
}
function WriteErrorMessage($text)
{
Write-Host $text -fore green
}
$global:_savedErrorMessages = @()
function SaveErrorMessage($text)
{
$global:_savedErrorMessages += $text
}
function GetErrorMessages()
{
$global:_savedErrorMessages
}
June 2, 2009
Generate enum for AzMan Operations
I wrote this tool a long time ago and wanted to just point it out in my blog. It will generate for you an enum of AzMan operations that you can now call in your code. This was very handy for me in my applications.
Logparser SQL Server 2005 Log
Logparser is one of my favorite tools. Here is a simple query that will parse a sql server 2005 log:
SELECT TOP 25 extract_token(field1,0,' ') as Date, extract_token(field1,1,' ') as Time, extract_token(field1,2,' ') as Source, field2 as Message
FROM c:\sql.log
ORDER BY Date, Time DESC
AzMan Common Errors
Here is a list of common errors that I had while working with AzMan. I'll keep this updated if I come across any new ones (especially now with the SQL store as the new backend).
- Unable to update the password. The values provided as the current password is incorrect.
- COM error 80040154 or Retrieving the COM class factory for component with CLSID {...}
- File not found (80070002)
- Element not found (80070490)
- This operation can not be performed on the current domain.
- The specified domain either does not exist or could not be contacted
- The system cannot open the device or file specified 98007006
- Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Interop.Security.AzRoles.IAzApplication'
- The authorization store component is not installed
- FileLoadException: The process cannot access the file because it is being used by another process
This is an issue with the user making a call out to AzMan. You should set Everyone as a Reader or turn impersonation on (if cross-domain). You should see full details in the event log where AzMan is located.
The error is that .NET can't find the AzMan COM objects. If you copy azroles.dll into %WINDIR%\System32\and then run regsvr32 azroles.dll you should be ok. You can also GAC the Microsoft.Interop.Azroles.dll which is found in %WINDIR%\Microsoft.NET\AuthMan .
The solution for me was to Add the Authenticated Users to the Reader mode in AzMan. You can also try and add everyone (not the best idea) to the reader mode.
You usually get this when the msldap or msxml string is wrong. Check your connection string and make sure it can talk to the right domain or XML file. Also, I have seen this if you attempt to talk to an operationName or operationID that is not there or spelled incorrectly.
Seems to be tied to mismatched SIDs or going cross domain. Usually, this is just a trust issue. You can also try and impersonate to solve this problem. This error is tied to an AD backed store and you should not really see this in an XML store system.
A solution for this can be found Here. Personally, I never had this error happen to me.
Another security/trust issue. Make sure you have correct roles to read AzMan and the trusts or impersonation is set in place correctly.
Solution can be found Here.
Make sure you GAC the AzRoles Interop Assembly.
Something with how the DOM opens up XML. I never really had this issue as I oly worked with AD store.
AzMan on XP
I know that most people know this by now, but it was one of the major issues that I ran into. In order to get this working on XP you must download the adminpak.exe located Here.
AzMan (history lesson)
Before we actually dive into code and how to use AzMan within our applications, it is important to know what AzMan is.
AzMan was rolled into Windows Server 2003 a few years ago and did not really get that much attention. When I was building an application a few years ago, I needed a fine grained approach to authorizing users. I wanted a real RBAC system and something that I would be able to use within a .NET application. I read about this COM based API called AzMan that would be able to solve my problems. It is a full RBAC system and had a backing store (at the time) of AD or XML. The breakdown was basically that a user had a Role(s) and a Role was made up of other Role(s), Task(s), or operation(s). Tasks were made up of operation(s) or other Task(s) and operations were low level "methods". Another way would be to say that a role was Executive and Executive had a task of Exec and ExecTask had an operation of DoEverything.
Most people don't remember that Microsoft actually released some open source code to help with AzMan. Back in the day before EntLib, we had Microsoft Application Blocks. One of the blocks was Microsoft.ApplicationBlocks.Security. This had some form of a wrapper around the Interop, but it was very confusing. If you look back or serach Google you may be able to find the original AzManProvider.cs that Microsoft released. At that time, I wrote a wrapper around the wrapper that Microsoft wrote! Here is what it looked like:
That was some very old .NET 1.1 code and a wrapper around what Microsoft wrote. It allowed me to then do the following in my application:
Not the best, but it allowed me to at least get what I needed. From that point though, I ran into many issues with AzMan and also as newer versions of .NET came out my code changed dramatically. I'll share this as I cotinute writing posts on AzMan.
AzMan was rolled into Windows Server 2003 a few years ago and did not really get that much attention. When I was building an application a few years ago, I needed a fine grained approach to authorizing users. I wanted a real RBAC system and something that I would be able to use within a .NET application. I read about this COM based API called AzMan that would be able to solve my problems. It is a full RBAC system and had a backing store (at the time) of AD or XML. The breakdown was basically that a user had a Role(s) and a Role was made up of other Role(s), Task(s), or operation(s). Tasks were made up of operation(s) or other Task(s) and operations were low level "methods". Another way would be to say that a role was Executive and Executive had a task of Exec and ExecTask had an operation of DoEverything.
Most people don't remember that Microsoft actually released some open source code to help with AzMan. Back in the day before EntLib, we had Microsoft Application Blocks. One of the blocks was Microsoft.ApplicationBlocks.Security. This had some form of a wrapper around the Interop, but it was very confusing. If you look back or serach Google you may be able to find the original AzManProvider.cs that Microsoft released. At that time, I wrote a wrapper around the wrapper that Microsoft wrote! Here is what it looked like:
using System;
using System.Threading;
using System.Collections.Specialized;
using System.Security;
using System.Security.Principal;
using Microsoft.ApplicationBlocks.Security.Authorization;
namespace Microsoft.ApplicationBlocks.Security.Wrappers
{
///
/// Summary description for AuthorizationHelper.
///
public sealed class AuthorizationHelper
{
private ExtendedPrincipal principal;
public AuthorizationHelper(IIdentity ident, string auditID, String provName, string appName)
{
principal = ExtendedPrincipal.Create(ident);
Thread.CurrentPrincipal = principal;
principal.AuditIdentifier = auditID;
principal.AuthorizationProvider = provName;
principal.AuthorizationParameters.Add(AzManProvider.ApplicationName, appName);
}
public AuthorizationHelper(IIdentity ident, string auditID, String provName)
{
principal = ExtendedPrincipal.Create(ident);
Thread.CurrentPrincipal = principal;
principal.AuditIdentifier = auditID;
}
public bool CheckAccess(string scope, string operation)
{
principal.AuthorizationParameters["scope"] = scope;
principal.AuthorizationParameters["operation"] = operation;
return principal.CheckAccess();
}
public StringCollection GetRoles()
{
return principal.GetRoles();
}
public bool IsInRole(string role)
{
return principal.IsInRole(role);
}
}
}
That was some very old .NET 1.1 code and a wrapper around what Microsoft wrote. It allowed me to then do the following in my application:
AuthorizationHelper auth = new AuthorizationHelper(WindowsIdentity.GetCurrent(), "auditID", "azmanProvider", "TestApplication");
lstRoles.DataSource = auth.GetRoles();
lstRoles.DataBind();
Not the best, but it allowed me to at least get what I needed. From that point though, I ran into many issues with AzMan and also as newer versions of .NET came out my code changed dramatically. I'll share this as I cotinute writing posts on AzMan.
June 1, 2009
Get Modified users in AD using Powershell and C#
Using c# within powershell you can easily get users that have changed in AD. Just change the date found in the whenChanged part of the query (20090601):
$strFilter = "(&(objectClass=User)(whenChanged>=20090601000000.0Z)(userAccountControl:1.2.840.113556.1.4.803:=2))"On a side note, you can also do this very easily with the free Quest AD cmdlets
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$colProplist = "name"
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{$objItem = $objResult.Properties; $objItem.name}
IronPython
I avoided it for a while, but it seems I may soon have to dive into it. Time to start learning it: Hello World in IronPython!
Remote Execution of Powershell
Powershell 2 has some really cool features. One of the features I really like is the remoting portion. Although does not work on Vista, for me I just needed it to work on Win2k3. You will also need powershell installed on that server you are trying to connect to.
Here is some sample code and a helper script (thanks to my co-worker 'AC' for this one) to get it to work:
Here is some sample code and a helper script (thanks to my co-worker 'AC' for this one) to get it to work:
function ExecuteScriptRemotely($script, $scriptArgs, $server, $cred, $logFile)Here is how you would use it:
{
$cmd = " & { $script } $scriptArgs "
if($logFile)
{
$cmd += " > `"{0}`"" -f $logFile.Replace('"', '')
}
$encodedCommand = EncodeCommand $cmd
$commandLine = "powershell -ExecutionPolicy Bypass -EncodedCommand $encodedCommand"
StartRemoteProcess $commandLine $server $cred
}
function StartRemoteProcess($commandLine, $server, $cred)
{
if($cred)
{
Invoke-WMIMethod -path win32_process -name create -argumentList $commandLine -credential $cred -computerName $server
}
else
{
Invoke-WMIMethod -path win32_process -name create -argumentList $commandLine -computerName $server
}
}
function EncodeCommand($expression)
{
#Convert the command into an encoded command for PowerShell
$commandBytes = [System.Text.Encoding]::Unicode.GetBytes($expression)
$encodedCommand = [Convert]::ToBase64String($commandBytes)
$encodedCommand
}
function CreateCredentials($user, $password)
{
$password = convertto-securestring $password -asplaintext -force
New-Object System.Management.Automation.PSCredential $user, $password
}
$MY_DIR = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent
. (Join-Path $MY_DIR RemHelper.ps1)
# Create c:\bar.txt
$script = '"foo" > "c:\bar.txt"'
# run notepad
$script = 'notepad'
$scriptArgs = $null
$server = "MyServer"
$user = "Admin"
$password = "Password"
$cred = CreateCredentials $user $password
ExecuteScriptRemotely $script $scriptArgs $server $cred "c:\log.txt"
Messed up my Portable HD
Ughh...I messed up my Passport HD. I converted it to NTFS and I forgot that my DVD player reads Fat32. I'd call this a brain-freeze for the day! I needed to convert back to Fat32 and wanted a fast utility. I found Fat32Format to be the fastest option.
...have to backup my music before I format though!
...have to backup my music before I format though!
Transcript Log in Powershell
How many times have you typed up a script and then by accident closed the command prompt. I can tell you it has happened to me a few times! Sure, I can probably whip it up again in a few minutes, but it is annoying! Well, here is something that I came across:
There are a few things to note with this:
Start-Transcript D:\tmp\Transcript.txtThis will create a log called Transcript.txt that contains everything you did with powershell for that session. If you like, you can have it start up each time by setting this in your environment on powershell startup.
# Do some work
get-wmiobject win32_computersystem
Stop-Transcript
There are a few things to note with this:
- This will write over any previous sessions unless you set it up to append by using -Append $true in your Start-Transcript
- This works only in the command line and not in the ISE. I guess this was missed?
- This will log everything you type within the session
May 31, 2009
Free e-book on Powershell
I know a few exist online, but I really like the Effective Windows Powershell written by Keith Hill. You can download it HERE
Replace macro fields with Ruby
OK, now let's do it in Ruby. This requires a values.rb folder (like our values.ps1 folder in powershell):
require 'erb'
require 'rio'
module MacroConfig
def self.generate
mkdir_if_not_exist 'configs'
Dir.glob('templates/*').each do |template_file|
template = ''
rio(template_file) > template
config = ERB.new(template).result(get_values)
config_file = 'configs/' + File.basename(template_file)
rio(config_file) < script =" ''">> script
script << "\n"
end
eval script
binding
end
def self.get_values
read_values(['../values.rb', 'values.rb'])
end
def self.mkdir_if_not_exist(dir_name)
Dir.mkdir dir_name unless File.exist? dir_name
end
end
Subscribe to:
Posts (Atom)