Archive for the 'Scripting' Category
December 28th, 2011 by Michael
We use Citrix for a lot of applications, and I have a need to launch Outlook, then an application, and then close Outlook when that application is closed by the user. This seems like a pretty simple thing to do (and I suppose it is, sort of) but it took me a while to figure it out.
One piece of the puzzle is that PowerShell remains open if you do it the way I have it setup right now. If the user closes that PowerShell window, then the monitor process will not close Outlook when the user exits the LOB app. In order to mitigate this issue somewhat, I wanted to start PowerShell minimized. The way to do this is:
powershell -WindowStyle Minimized .\ScriptToRun.ps1
July 29th, 2010 by Michael
If you want to know what logon script users are getting, this is an easy way to get that information:
Import-Module -Name ActiveDirectory
Get-ADUser -Filter * -SearchBase "OU=YourOUName,DC=YourDomain,DC=COM" -properties ScriptPath | Export-Csv "c:\script\ADUser.csv"
Note: In order for this to work, you have to have the ActiveDirectory Module loaded.
March 25th, 2010 by Michael
I have been working on a simple little script to copy a file and then launch a program. I am sure that there are a lot of ways to do it, but I decided to use PowerShell, and this is what I came up with:
$CheckForFile = "H:\custom.ini"
$FileToCopy = "c:\IT\custom.ini"
$CopyFileTo = "H:\"
$PathTest = Test-Path $CheckForFile
If ($PathTest -eq "false")
{
Copy-Item $FileToCopy $CopyFileTo
}
#uses the Invoke-Item command to launch the application
Invoke-Item "C:\Program Files\executable to launch.exe"
This is for use in a Citrix/Terminal Server environment, so I want to be able to call this script like this: PowerShell copythenlaunch.ps1
When I tested that, I got this:
C:\IT>powershell copythenlaunch.ps1
The term ‘copythenlaunch.ps1′ is not recognized as a cmdlet, function, operable
program, or script file. Verify the term and try again.
At line:1 char:18
+ copythenlaunch.ps1 <<<<
I kept thinking there was some problem with the install of PowerShell (I am running this particular script on a Windows 2003 Server) or that I had some illegal character in the name (it had a number in it originally) or some other simple problem. Finally I did a search and came across this little bit of conversation:
re: Power and Pith
I just started with PowerShell.
Wanted to run some test scripts from you download.
When I tpye in Beep.ps1 I get "The term ‘Beep.1′ is not recognized….."
What Am I doing wrong?
Friday, December 29, 2006 3:17 PM by MikeL
# re: Power and Pith
> When I tpye in Beep.ps1 I get "The term ‘Beep.1′ is not recognized….."
> What Am I doing wrong?
You are relying upon a traditional bad shell behaviour that has been a security nightmere for decades.
In PowerShell, you have to be explicit if you want to run a command in the current directory. Type ".\beep.ps1"
Jeffrey Snover [MSFT]
Windows PowerShell/MMC Architect
Visit the Windows PowerShell Team blog at: http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at: http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx
Friday, December 29, 2006 5:19 PM by PowerShellTeam
# re: Power and Pith
Thank You for supplying the ".\*" information. I have been racking my brain for almost two days wondering what I was doing wrong. And to think it was as simple as using the PROPER .\yourscripthere.ps1 format.
Thank you very very much
Ditto on the thanks…
Windows PowerShell Blog : Power and Pith
March 4th, 2010 by Michael
I seem to run into an issue when I run some PowerShell scripts where I get prompted at each line of the script for confirmation. That can get really annoying, so I have to look up how to prevent that behavior. Thankfully, there is already some good information out there on how to do that:
When confirmation is turned on by $ConfirmPreference, you can turn it off for any individual cmdlet invocation using "-Confirm:$false". You can also use "-Confirm:$false" to turn off default confirmation for high impact cmdlets such as Removing a Mailbox. Another way to turn off confirmation is by setting $ConfirmPreference to "None"; you can limit the effect by setting $script:ConfirmPreference etc, see "get-help about_scope" for more details.
For more details and options besides just turning it off, go see the original post:
Windows PowerShell Blog : ConfirmPreference
February 24th, 2010 by Michael
At some point, I had a desire to list all the computer accounts for any server OS in Active Directory. I am pretty sure that I did a search and found the script below, but I don’t remember where, so whoever wrote it doesn’t get credit this time…
$strCategory = “computer”
$strOperatingSystem = “Windows*Server*”
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.Filter = (“OperatingSystem=$strOperatingSystem”)
$colProplist = “name”
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$colResults = $objSearcher.FindAll()
Write-Host $colResults.count
foreach ($objResult in $colResults)
{
$objComputer = $objResult.Properties;
$objComputer.name
}
If you change the $strOperatingSystem = “Windows*Server*” to something like $strOperatingSystem = “Windows*” it will return all computer accounts that have “Windows” in the Name field on the Operating System tab of the properties of the AD object:

September 22nd, 2009 by Michael
I have written a lot of scripts that use .txt files to read or store data, but I have a need to read some information from an .xml file. This could be done by treating the file as a simple txt file, but it would require some pretty good filtering that is already a part of the xml file. A quick search helped me locate this article:
http://blogs.msdn.com/kalleb/archive/2008/07/19/using-powershell-to-read-xml-files.aspx
Which contained the key to helping me with what I needed to do. The specific piece I needed was in Lesson 2:
Lesson 2:
Read data from an XML-file.
The XML-file that I’m going to read from has the following structure:
<Users>
<User>
<Name>Kalle</Name>
</User>
<User>
<Name>Becker</Name>
</User>
</Users>
Reading data from an XML-file is really easy in PowerShell! Use this command to load the file into an variable:
PS C:\Tmp> [xml]$userfile = Get-Content Accounts.xml
When the xml-file is loaded you can type “$userfile.U” and press tab to get auto completion!! It’s a breeze.
The trick is that you have to actually READ what is in front of you. The key here is to let PowerShell know that you are reading an xml file, and that is done by placing [xml] prior to getting the content. I missed that the first six times I read this and couldn’t figure out why I wasn’t getting the results I expected.
September 4th, 2009 by Michael
One of the things that we spend a lot of time on is trying to keep track of what servers have enough free space. We have a lot of different tools to check drive space, and we even use some of them from time to time. We have a pretty complicated system created by Rickey that creates a nice webpage, with highlighting for problem areas (percentage change from day to day, current percent free, etc.) It even puts the info into a database for historical reporting.
We don’t store or report on VMs currently, mainly because we were trying to keep track of total REAL disk used. VMs often don’t use as much as they think they do, so that would skew the results, as well as the fact that we are reporting on the hosts.
All of that is the reason that Patrick asked me to come up with some other tool to use for the VMs so I happened to find a few pieces of PowerShell script that I managed to put together to do a pretty good job of providing some of the info we wanted, and I thought I would share that with the 2 people who read my blog.
$servers = Get-Content servers.txt
#Open Excel and create a new workbook and worksheet
$ExcelSheet=New-Object -comobject Excel.application
$WorkBook=$ExcelSheet.WorkBooks.add(1)
$WorkSheet=$WorkBook.WorkSheets.item(1)
#Header row
$WorkSheet.cells.item(1,1)=”Computer Name”
$WorkSheet.cells.item(1,2)=”Disk Device ID”
$WorkSheet.cells.item(1,3)=”Volume Name”
$WorkSheet.cells.item(1,4)=”Size (GB)”
$WorkSheet.cells.item(1,5)=”Free Space (GB)”
$WorkSheet.cells.item(1,6)=”Space Used (GB)”
$WorkSheet.cells.item(1,7)=”Percent Used”
$i=2
ForEach ($ComputerName in $servers)
{
echo "Server Name : ", $ComputerName
$Disks = gwmi –computername $ComputerName win32_logicaldisk -filter "drivetype=3"
foreach ($Disk in $Disks)
{
$Size = "{0:0.0}" -f ($Disk.Size/1GB)
$FreeSpace = "{0:0.0}" -f ($Disk.FreeSpace/1GB)
$Used = ([int64]$Disk.size – [int64]$Disk.freespace)
$SpaceUsed = "{0:0.0}" -f ($Used/1GB)
$Percent = ($Used * 100.0)/$Disk.Size
$Percent = "{0:N0}" -f $Percent
$WorkSheet.cells.item($i,1)=$ComputerName
$WorkSheet.cells.item($i,2)=$Disk.deviceid
$WorkSheet.cells.item($i,3)=$Disk.volumename
$WorkSheet.cells.item($i,4)=$Size
$WorkSheet.cells.item($i,5)=$FreeSpace
$WorkSheet.cells.item($i,6)=$SpaceUsed
$WorkSheet.cells.item($i,7)=$Percent
$i=$i+1
}
}
#Show the results
$ExcelSheet.visible=$true
March 11th, 2009 by Michael
I have the unfortunate need to occasionally fix things in the registry, mostly related to applications running in a Citrix environment. I believe there are nice tools out there that are supposed to do this for you, if given the right information, but I haven’t bothered to figure out what those tools are or how to use them. Instead, I torture myself with trying to muddle through VBScript and make it do what I want.
In that spirit, I am going to show you one of my pitiful scripts (and this one is horrible, because I didn’t bother to clean it up after I worked out how to make it accomplish the desired goal. So… here you go:
‘==========================================================================
‘
‘ VBScript Source File — Created with SAPIEN Technologies PrimalScript 2007
‘
‘ NAME: BorlandDBPathFix.vbs
‘
‘ AUTHOR: Michael Phillips , Brasfield & Gorrie, LLC
‘ DATE : March 11, 2009
‘
‘ COMMENT: This script is to change the value of 2 registry keys on a per
‘ user basis. It should set the value to be the correct system
‘ drive (c: or u:).
‘ It should also be noted that this script isn’t very pretty.
‘==========================================================================
‘Registry stuff
Const HKCU = &H80000001 ‘This defines the Current User Hive
Const HKLM = &H80000002 ‘This defines the Local Machine Hive
Const REG_SZ = 1
Const REG_EXPAND_SZ = 2
Const REG_BINARY = 3
Const REG_DWORD = 4
Const REG_MULTI_SZ = 7
vDebug = 1
Dim strComputer
strComputer = “.” ‘This computer is the “.”. If you want another computer, replace the .
Set oReg=GetObject(“winmgmts:{impersonationLevel=impersonate}!\\” & _
strComputer & “\root\default:StdRegProv”)
sGetPath
Sub sGetPath
Set oShell = CreateObject( “WScript.Shell” )
strSystemDrive = oShell.ExpandEnvironmentStrings(“%systemdrive%”)
‘* wscript.echo strSystemDrive
fGetRegistryValues strSystemDrive
End Sub
‘*
‘* This is what we are looking for:
‘* [HKCU\Software\Borland\BDS\4.0\DBExpress]
‘* @=”"
‘* “Connection Registry File”=”C:\\Program Files\\Common Files\\Borland Shared\\DBExpress\\dbxconnections.ini”
‘* “Driver Registry File”=”C:\\Program Files\\Common Files\\Borland Shared\\DBExpress\\dbxdrivers.ini”
Function fGetRegistryValues (vSystemDrive)
‘* wscript.echo vSystemDrive & ” is being passed as vSystemDrive”
oReg.GetExpandedStringValue HKCU,”Software\Borland\BDS\4.0\DBExpress”,”Connection Registry File”,strValue1
oReg.GetExpandedStringValue HKCU,”Software\Borland\BDS\4.0\DBExpress”,”Driver Registry File”,strValue2
strDriveLetter1 = Left (strValue1,2)
‘* wscript.echo strDriveLetter1 & strValue1 & strSystemDrive
strDriveLetter2 = Left (strValue2,2)
If strDriveLetter1 = vSystemDrive Then
If strDriveLetter2 = vSystemDrive Then
Else
fSetRegistryValues strValue1,strValue2,vSystemDrive
End If
Else
fSetRegistryValues strValue1,strValue2,vSystemDrive
End If
End Function
Function fSetRegistryValues (fValue1,fValue2,fDriveLetter)
‘* wscript.echo “Bad Letter is being passed ” & fValue1 & fValue2 & fDriveLetter
vLength1 = (Len (fValue1))-2
vLength2 = (Len (fValue2))-2
‘* wscript.echo “–strValue1 & vLength1– >” & fValue1 & ” ” & vLength1
strPathNoLetter1 = Right (fValue1,vLength1)
strNewKeyValue1 = fDriveLetter & strPathNoLetter1
fWriteStringRegistryValues “Software\Borland\BDS\4.0\DBExpress”,”Connection Registry File”,strNewKeyValue1
‘* wscript.echo strNewKeyValue1
strPathNoLetter2 = Right (fValue2,vLength2)
strNewKeyValue2 = fDriveLetter & strPathNoLetter2
fWriteStringRegistryValues “Software\Borland\BDS\4.0\DBExpress”,”Driver Registry File”,strNewKeyValue2
‘* wscript.echo (fDriveLetter & (Right (fValue2,vLength2)))
End Function
Function fWriteStringRegistryValues (fvRegistryKeyPath,fvRegistryKeyName,fvRegistryKeyValue)
If vDebug = 1 Then
‘* wscript.echo “Begining Function -fWriteStringRegistryValues-.”
End If
‘ This function takes input to write string values to the registry. Key must already exist.
oReg.SetStringValue HKCU,fvRegistryKeyPath,fvRegistryKeyName,fvRegistryKeyValue
End Function
September 7th, 2007 by Michael
I was looking for something else and came across this in the Scripting guy archives…
Set objFile = objFSO.OpenTextFile("c:\scripts\test.txt", ForReading,False,TriStateTrue)
The first two parameters probably don’t faze you much: they’re simply the full path to the file we want to open and the constant ForReading. And you’re right: this is standard operating procedure when it comes to reading text files. But what about those other two parameters, one False, the other the constant TriStateTrue?
This is where the Scripting Guys perform their magic. The optional third parameter is a Boolean parameter that, if True, creates the specified text file if the file cannot be found. Because we’re only interested in opening an existing file, we set this parameter to False (which is also the default value).
That brings us to parameter 4, our old pal TriStateTrue. If the fourth parameter passed to the OpenTextFile method is equal to -1 then the file will be opened as a Unicode file. It’s that easy. Leave the fourth parameter off and the file will be opened as ASCII; set the fourth parameter to -1 and – presto-changeo! – your file will be opened as Unicode,
Hey, Scripting Guy! How Can I Open a Text File as Unicode?
August 29th, 2007 by Michael
I was trying to write a script to read a text file and evaluate the data to do some formatting on it. This is for a project I am working on and the person that gave me the text file wants some changes made based on the contents of the file. I have done similar things before, but I kept having trouble with this one.
I started with trying to do a readline and then echo that back. Every time I tried it, I got ÿ_[ (y with the umlaut, underscore and the bracket)as the output for the first line and then nothing for everything after that. I tried it against other text files and got the expected result. I was investigating, trying to figure out if there was a character in the file that didn’t work well, and finally decided to try and do a writeline to another text file to see if it would at least write the value out that way.
Imagine my surprise when the results came back with a space between each letter in the source file. Turns out that it was in UNICODE format. I saved it as ANSI and then everything was golden. I also noticed that the file was half the original size… must have to do with all those extra spaces…