Thursday, 29 March 2012

How to get the current epoch time in ...

this site is awesome. when you need to know how to get an epoch from a date for vice versa in many different platforms (sql, unix, vbscript, asp etc...)

http://www.epochconverter.com/

Sunday, 25 March 2012

exporting attachments from outlook pst file

made the final move of my legacy local email into 'the cloud' this week, and needed a solution to export the years of pictures and files out of my wife's 700 MB outlook pst file that we never got round to saving outside outlook.

Its funny how all those quick email checks over the years and thinking 'I'll save those pictures into my pictures later' adds up into a massive job.

this plugin for outlook "Outlook Attachment Remover Add-in"

is magic and did the job perfectly so I'd highly recommend it to anyone faced with the same dilemma (or even as a way of keeping the pst file size down as its actually intended for.) It grinded away for a about 10 minutes and now I have several thousand files in one nice folder on my hard disk. AWESOME!

What is really cool is it replaces your attachment with a shortcut in the pst to where the file is saved on the computer so you can keep the pst file size down.

Personally I've always thought pst files were devil spawn (I used to be a IT system admin and they were a scourge... we had 50MB mailbox allowances back then and people would build up GB size PST files and store them on our shared network drives). Now we have the 'cloud' and what once were unthinkable size free online storage...


Tuesday, 28 February 2012

loving xkpasswd

it seems a sad reality of modern life that you have a million passwords to manage often with different rules.

I'm loving www.xkpasswd.net to generate memorable secure passwords.

Tuesday, 8 November 2011

CA System edge 5.x ca-setup.sh temp space bug - he '1.0.1.0' temporary directory does not have enough free space

installing new *nix ca-setup.sh script and had temp space errors. There is a bug in the script on the CA virtual assurance for infrastructure manager agent for unix dvd in this script. the line that checks temp space reads used space as free space so will fail if /tmp is almost empty.


You get this error when there is plenty of free space in /tmp if you have almost no used in /tmp and install fails.
CA-setup bootstrapper version 1.0.1.0
The '1.0.1.0' temporary directory does not have enough free space. Aborting installation.

Lack of free space??? I don’t think so my /tmp is 2gb and 2% used!
df -P -k /tmp
Filesystem         1024-blocks      Used Available Capacity Mounted on
/dev/mapper/vg00-tmpvol   2030995     38471   1887782       2% /tmp

Debugging where this comes from shows:

+ checkTmpSpace
++ du -ks .
++ awk '{print $1}'
+ NEED_SPACE=53616
++ expr 53616 + 100
+ NEED_SPACE=53716
++ df -P -k /tmp
++ tail -1
++ awk '{print $3}'
+ FREE_SPACE=38470
+ '[' 38470 -lt 53716 ']'
+ logExitWithMsg 1 TMP_TOO_SMALL


Here is the function
checkTmpSpace()
{
    # Find how much space is in the current dir.
    NEED_SPACE=`du -ks . | awk '{print $1}'`
    # Add a bit extra just for case.
    NEED_SPACE=`expr $NEED_SPACE + 100`
    # Find how much free space is in temporary location.
    FREE_SPACE=`df -P -k $CA_SETUP_TMPDIR | tail -1 | awk '{print $3}'`
    if [ $FREE_SPACE -lt $NEED_SPACE ]
    then
        logExitWithMsg 1 TMP_TOO_SMALL
    fi
}

If you look closely at the output the function read you wil see it should be {print $4} not print $3 because it is reading the USED value 38471   as FREE instead of 1887782       

Sunday, 11 September 2011

Deleting a user who created SCOM/operations manager scheduled report stops report from running

one annoying issue that came up for us recently after some user housecleaning in SCOM. If you delete the active directory user who created a scheduled system center operations manager report the scheduled report will no longer run and there is no easy way to rectify the problem. This is a similar problem to what happens if you delete the user who created a notification subscription although in that case the user SID's can be edited by export/import of the notification management pack. however this scheduled report problem stems from the SRS MS SQL Report server database 'creator' attribute for a report subscription and is not a problem in operations manager at all.

After much scouring of the net I found this post which is a solution but I thought I would post it here so if you are searching for 'OperationsPublish Post Manager 2007 r2 deleted creator user scheduled report won't run' or something similar you will hit upon the solution very quickly!


Monday, 13 June 2011

VBSShell - embed a powershell script in a vbscript and setting ExecutionPolicy from registry

I recently had a situation where I could deploy a vbscript to lots of machines remotely via another product but it wouldn't do powershell natively which was a shame because I had a great powershell script to do the job I wanted to achieve right then.

So I wrote this script I called VBSShell that is a vbscript wrapper for a embedded powershell script.

When executed on a machine it will extract the embedded string to a ps1 file in %temp% then execute it and capture the output.

if powershell execution policy is not >=RemoteSigned script has logic to:
- abort
- edit setting temporarily via Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell\ExecutionPolicy
- alternately permanently change the setting (not recommended by me!!)

I also wrote  a second script to encode a ps1 file as a second file containing the string to paste into the vbsshell wrapper because its a bit of a pain doing it by hand (because " is invalid!)

I've pasted the two scripts below


' VBSShell
' vbscript powershell wrapper.
' useful if you have a situation where you want to run a powershell on a machine via a package system that only allows you to run a vbs
' this script will
' 1) find powershell and store binary location (exit if not found)
' 2) make a 'local' ps1 file of the script content
' 3) create a batch file in .tmp to execute and > output to temp file
' 4) read script output and echo so you can see in vbscript output what the script did + errors

' note regarding powershell script security
' by default powershell will not permit ps1 scripts.
' for vbs to execute a powershell script the policy must be >="RemoteSigned" at some point typically by "Set-ExecutionPolicy RemoteSigned" in ps prompt.
' there are flags below that allow you to control the behavour of this script around this issue.
' options include:
' - exit if PS policy to restrictive and do nothing.
' - temporarily set to RemoteSigned then revert at script end
' - permanently set to RemoteSigned

' Note - debug mode
' there is a debug sub at end of script. uncomment this sub's echo to enable extended logging to STDOUT

' version
' 1.03

' error control (to ensure script ends if any ps policy change)
On Error Resume Next

' ################################# CONFIG OF PS1 CONTENT ######################################

' ENTER PS1 FILE CONTENT HERE
' note you will have to replace " with chr(34) or """" unfortunately...
' and this can be tricky as open quote should be chr(34) & " vs closing quote " & chr(34)
' you can import a file here instead but for my purpose if I could do that in the application I need this for I wouldn't have written this script!
' you can use encoder.vbs in this folder to create encoding for ps1 file.

Dim ps1Content

ps1Content= " # example.ps1 to demo encoding file " & vbcrlf & _
" # This is a powershell test script " & vbcrlf & _
"  " & vbcrlf & _
" $a = 1 + 1 " & vbcrlf & _
" " & """" & "1+ 1 = $a" & """" & " " & vbcrlf & _
"  " & vbcrlf & _
" dir | format-List " & vbcrlf & _
"  " & vbcrlf & _
" # the end " & vbcrlf & _
"exit"


' ** WARNING END ALL SCRIPTS WITH "exit" *** or you will make this script potentially hang indefinitely waiting for the ps prompt to close!!

' ################################### SETUP SOME GLOBAL OBJECTS #############################################
Const ForReading = 1, ForWriting = 2, ForAppending = 8
const HKEY_LOCAL_MACHINE = &H80000002

Set WshShell = CreateObject( "WScript.Shell")
Set oFSO = CreateObject("Scripting.FileSystemObject")

dim ThisScript,ThisPath,ScriptName,TEMPDir,epoc

' epocnow time used to stamp files
epocnow = datediff("s","01/01/1970 00:00",now)

ThisScript = wscript.ScriptFullName ' name of the script including path.
ThisPath =  Left(ThisScript, InstrRev(ThisScript, "\")) ' path where script is run - used for relative pathing
ScriptName = right(thisScript,len(thisscript)-len(thispath))

TEMPDir = WshShell.ExpandEnvironmentStrings("%TEMP%")

if right(TEMPDir,1)="\" then

else
TEMPDir=TEMPDir & "\"
end If

debug TEMPDir

' ################################## CONFIG FOR POWERSHELL #########################################

' possible values for powershell security (get/set-executionpolicy)
' "not set" == Restricted
'Restricted (default)
'AllSigned
'RemoteSigned
'Unrestricted
' this script can only succeed where >=RemoteSigned

' set this value to true to set "RemoteSigned" if more restrictive policy in place
' the vbs will set policy to RemoteSigned if required if this is true otherwise if can't proceed error
'Const PowershellOverride = false
Const PowershellOverride = true

' set this value to true to revert to previous powershell setting (if you set Powershelloverride to true)
' if true and change made will revert to previous value at end of script.
' **** RECOMMENDED SETTING IS TRUE TO AVOID PERMANENT CHANGE TO SECURITY SETTING *****
Const PowershellRevert = true

Dim powershellBin,CurrentpsPolicy,TemppsPolicy,CanGo,PsChanged
CanGo=False
PsChanged=false
CurrentpsPolicy=Null
TemppsPolicy = "RemoteSigned"

' read current powershell path
if ReadRegStringValue(HKEY_LOCAL_MACHINE,"Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell","Path",powershellBin) Then

wscript.echo "powershell: " & powershellBin
Else
debug "ERROR no: Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell-Path. Powershell not installed??"
wscript.quit(1)
End If

' read current execution policy
if ReadRegStringValue(HKEY_LOCAL_MACHINE,"Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell","ExecutionPolicy",CurrentpsPolicy) Then
wscript.echo "powershell: " & CurrentpsPolicy
Else
debug "ERROR can't read: Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell-ExecutionPolicy"
wscript.echo "Assume Restricted"
CurrentpsPolicy = "Restricted"
' wscript.quit(2)
End If

If CurrentpsPolicy = "Restricted" Then
CanGo=false
ElseIf CurrentpsPolicy = "AllSigned" Then
CanGo=false
ElseIf CurrentpsPolicy = "RemoteSigned" Then
CanGo=true
ElseIf CurrentpsPolicy = "Unrestricted" Then
CanGo=true
Else
CanGo=false
debug "ERROR unknown value for PSPolicy: " & CurrentpsPolicy
wscript.quit(3)
End If

debug CurrentpsPolicy

If CanGo = True Then

Else
If PowershellOverride = True Then
PsChanged = true
WSCRIPT.ECHO "OVERRIDE PS POLICY AS OVERRIDE FLAG SET "
If WriteRegStringValue(HKEY_LOCAL_MACHINE,"Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell","ExecutionPolicy",TemppsPolicy) Then
wscript.echo "Powershell Policy set to " & TemppsPolicy
Else
wscript.echo "ERROR overriding PS Policy"
wscript.quit(5)
End if
Else
wscript.echo "CANT PROCEED as powershell policy too restrictive: " & CurrentpsPolicy
wscript.quit(4)
End If

End If


' ######################################## END POWERSHELL CONFIG   #####################################

' show content for debug
debug ps1Content


' now create the local text file containing the ps1
' and the bat file

Dim ps1name, filehandle, batname, outname

ps1name = TEMPDIR & ScriptName & epocnow & ".ps1"

' debug
'wscript.echo ps1name
Set filehandle = oFSO.OpenTextFile(ps1name,ForWriting,true)
filehandle.write ps1Content
filehandle.close

outname = TEMPDIR & ScriptName & epocnow & ".tmp"
batname =  TEMPDIR & ScriptName & epocnow & ".bat"

'debug
'wscript.echo batname
'wscript.echo outname

Set filehandle = oFSO.OpenTextFile(batname,ForWriting,true)
filehandle.writeline powershellBin & " " & Chr(34) & ps1name & Chr(34) & " > " & outname
filehandle.close

' execute the ps1 which is local to set-execution policy remotesigned should allow
WshShell.Run batname,7,true
DEBUG batname

Dim Output
Set filehandle = oFSO.OpenTextFile(outname,ForReading)
Output = filehandle.readall
filehandle.close

DEBUG outname

wscript.echo "** SCRIPT EXECUTED WITH OUTPUT: " & vbcrlf & output

' if changed policy do you want to revert?
If PsChanged=True Then
If PowershellRevert=True then
WSCRIPT.ECHO "REVERT powershell execution policy BACK TO : " & CurrentpsPolicy
If WriteRegStringValue(HKEY_LOCAL_MACHINE,"Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell","ExecutionPolicy",CurrentpsPolicy) Then
wscript.echo "Powershell Policy set to " & CurrentpsPolicy
Else
wscript.echo "ERROR overriding PS Policy. Policy still set to " & TemppsPolicy
wscript.quit(6)
End If
else
wscript.echo "WARNING - powershell execution modified at your request from: " & CurrentpsPolicy & " to " & TemppsPolicy
End if
Else
End if

Set WshShell = nothing
Set oFSO = nothing

wscript.quit(0)

' ############## FUNCTION #########################
' if ReadRegStringValue(HKEY_LOCAL_MACHINE,"Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell","ExecutionPolicy",MyVariable) Then
Function ReadRegStringValue(KEY,strKeyPath,strValueName,ByRef strValue)
' returns true if value exists and false if doesn't exist
' strValue set to content of registrystring
' can return null if wmi connect fails
ERR.CLEAR
strValue=""
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
If Not err.number = 0 Then
debug "ERROR:  can't read registry"
ReadRegStringValue = FALSE
ERR.CLEAR
Else
debug "reading " & KEY & "\" & strKeyPath & "\" & strValueName
oReg.GetStringValue KEY,strKeyPath,strValueName,strValue
if isnull(strValue) OR err.number > 0 then
debug "ERROR:  can't read string value  " &strKeyPath & "\" & strValueName
strvalue=""
ReadRegStringValue = FALSE
else
debug "Read string value from : "& strKeyPath & "\" & strValueName  & " of " & CHR(34) & strValue & CHR(34) & " LEN: " & LEN(STRVALUE)
ReadRegStringValue = TRUE
end if
End If
End Function

Function WriteRegStringValue(KEY,strKeyPath,strValueName,strValue)
' returns true if value exists and write succeed
ERR.CLEAR
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
If Not err.number = 0 Then
debug "ERROR:  can't read registry"
WriteRegStringValue = FALSE
ERR.CLEAR
Else
debug "writing " & KEY & "\" & strKeyPath & "\" & strValueName
oReg.SetStringValue KEY,strKeyPath,strValueName,strValue
if not err.number = 0 then
debug "ERROR:  can't write string value  " &strKeyPath & "\" & strValueName
WriteRegStringValue = FALSE
else
debug "Wrote string value to : "& strKeyPath & "\" & strValueName  & " of " & strValue
WriteRegStringValue = TRUE
end if
End If
End Function

Sub debug (AString)
' comment me for prod!
wscript.echo "D: " & AString & " "  & err.number & " " & err.description
Err.clear
End sub




****************** encoder.vbs *****************************
' VBSShell
' vbscript powershell wrapper encoder script
' this script will convert a ps1 text file to a output file in same dir that is in right format to paste into the config section of the vbsshell script
' i.e with quotes etc

' version
' 1.01

' ENTER NAME OF THE PS1 FILE YOU WANT TO ENCODE TO PASTE INTO VBSSHELL HERE
' it should be in local folder of this script.
ps1name = "example.ps1"

Dim ps1Content
Dim ps1name, filehandle, outname,aline


' ################################### SETUP SOME GLOBAL OBJECTS #############################################
Const ForReading = 1, ForWriting = 2

Set oFSO = CreateObject("Scripting.FileSystemObject") 

dim ThisScript,ThisPath,ScriptName

ThisScript = wscript.ScriptFullName ' name of the script including path.
ThisPath =  Left(ThisScript, InstrRev(ThisScript, "\")) ' path where script is run - used for relative pathing

' prefix local path
ps1name = ThisPath & ps1name 

' debug
wscript.echo ps1name
Set filehandle = oFSO.OpenTextFile(ps1name,ForReading,true)

' set to blank
ps1Content=""

Do While filehandle.AtEndOfStream = False
aline = filehandle.readline

aline = Replace(aline,Chr(34),Chr(34) & " & " & Chr(34)& Chr(34) & Chr(34) & Chr(34)& " & " & Chr(34),1,99)
aline = Chr(34) & " " & aline & " " &  Chr(34) & " & vbcrlf & _ " & vbcrlf
ps1Content = ps1Content & aline 
Loop
filehandle.close

' ** WARNING END ALL SCRIPTS WITH "exit" *** or you will make this script potentially hang indefinitely waiting for the ps prompt to close!!
ps1Content=ps1Content & """" & "exit" & """" & vbcrlf

outname=ps1name & ".out.txt"
wscript.echo outname


' now create the local text file containing the ps1 encoded to paste
Set filehandle = oFSO.OpenTextFile(outname,ForWriting,true)
filehandle.write ps1Content
filehandle.close


Sunday, 10 April 2011

Counting SCOM / System Center Operations manager Enterprise Licences

SCOM 2007 has a builtin license report. Unfortunately if you override discoveries to remove 'enterprise ML liable' objects it is never reflected in this report so it always overstates your license count.

say for example you override exchange or sql MP so the exchange/sql objectss are not discvered it will still report these as enterprise license objects if they ever were discvoered at some point. I think this might be a problem that report can't tell between current and past licenses for an object. no matter how many objects of type Microsoft.SystemCenter.License.Enterprise you actually have in 'dicovered inventory'....

I've created a powershell script to spit out the objects right now that are the class objects for standard and enterprise liceses which is a 100% accurate count of what licenses you are really using right now.

############ Licencing ########################
$myclasses = "Microsoft.SystemCenter.License.Standard","Microsoft.SystemCenter.License.Enterprise"
foreach ($classname in $myclasses )
{ # get class
 $instances = get-monitoringClass -name $classname
 # get list as a string sorted by name and remove text that prefixes each name for some reason.
 $mylist = $instances | get-monitoringObject | select-object pathName | Sort-Object  pathname | out-string | foreach {$_ -replace "$classname3a","" }
 # output
 $mylist | foreach {$_ -replace "2d","-"} > c:\temp\SCOM_License_$classname.txt
}