Thursday, August 4, 2011

Windows 2008R2 and SCCM 2007 SP2 - Pt5 - Distribute software

One of the main reasons (amongst others) that you are going to use SCCM is probably to distribute software to clients and servers on your network.

To enable this functionality

  • Expand (in order) site database, site management, <your site>, site settings, site systems, <your server> and on the right pane, rightclick “ConfigMgr distribution point” and properties.
  • Select “Allow clients to transfer content from this distribution point using bits, http, and https ….)” and click OK

Add a package to the inventory

  • First, let’s download a nice utility called DoPDF. On that url, you’ll find a setup file. I’m saving it in the Downloads folder but in a subfolder called “DoPDF 7”.
  • On the SCCM console, expand (in order) site database, computer management, software distribution, packages
  • Rightclick packages and click “new -> package” and fill in the details (DoPDF, 7.x, DoPDF, English) and click Next.
  • Select “This package contains source files” and click on Set, “Local Drive …” and point to the folder where you’ve downloaded the msi file to. Click OK, Next, next, next, next, finish, close.

Add a program to the package
After creating the package, you can add one or more programs to the package.

  • Expand “DoPDF DoPDF 7.x English” and beneath that rightclick Program. Select New Program.
  • Name will be (again??) “DoPDF 7”, for commandline, browse to the directory and select the “dopdf-7.exe” but append the commandline with “/VERYSILENT /NORESTART”. These are however specific commands for this utility, so you’ll have to adapt for other installations. Click Next
  • Enter an estimation of the disk usage (so that the sccm client can abort the installation if a computer runs out of space) and the time the installation will approximately take. Optionally select specific platforms. Click Next.
  • At the environment level, you can specify whether the setup will run as the user currently logged on or with administrative rights. I suggest you set it to administrative rights and do not select “Allow user to interact with this program”. Click Next, Next, Next, Finish, Next, Close.

Distribute the package to a distribution point
There can be more than one distribution point in a bigger organization but in this case we only have to distribute it to one point.

  • Rightclick Distribution point and click “manage distribution points”. Click next, “copy the package to the new distribution points” + Next, select your SCCM server + Next, Next, Next, Close.
  • Expand “package status” untill you see your SCCM site, refresh, and in the right pane you’ll see the status of your package being copyed to your distribution point. “Installed” means it is transfered to the distribution point.

Assign the package to clients

  • Expand (in order) site database, computer management, software distribution, advertisement
  • Rightclick advertisement, New, Advertisement. I’m naming this taks “DoPDF 7.x for Windows 7 Clients”. Click on browse to select the DoPDF 7.x package. And click on browse to select a collection, in my case “All Windows 7 Systems” and click Next.
  • On schedule you can schedule this deployment to a specific date or time, you can even enable Wake-on-LAN if you want (but you’ll have to enable wake on lan on the site properties first!), but for now click on the yellow icon that looks like a sun and select “as soon as possible” and press OK. Click next.
  • On Distribution Point select “download from distribution point and run locally” on both occasions and click next, next, next, Finish, next, close.

The default polling interval of your clients is 60 minutes, so with a maximum of 60 minutes the installation will start.
You can set the interval higher at site settings -> client agents -> computer client agent properties. For this test environment it’s safe to set it to a really low value like 1-5 minutes, but in a bigger environment you don’t want to stress the SCCM server and your network.

Windows 2008R2 and SCCM 2007 SP2 - Pt4 - Collections

If, after installing SCCM 2007 SP2, you take a look at the collections (under Computer Management), you’ll see that it’s not really up to date. Servers up to Windows 2003 and workstations up to Windows XP are available, but no Windows 2008 (r2?) or Windows 7 is present.
If you are going to delegate tasks to systems, you might want or need some more finegrained collections.

Collections are based on query’s, so in order to create a new collection for Windows 7, we’re going to do the following:

  • Rightclick Collections, New Collection
  • Name and Comment: “All Windows 7 Systems”, click next
  • Click on the yellow database icon, set name to “All Windows 7 Systems”, resource class is “System Resource” and click on Edit Query Statement.
  • Go to the tab Criteria
  • Click on the yellow icon, click on the Select button
  • Attribute Class = “System Resource”, Attribute is “Operating system name and version”, click OK
  • Operator = “is like”
  • Value = “%Workstation 6.1%” (which basically means, if you combine it with the operator “is like”, that it must contain “Workstation 6.1”)
  • Click OK, OK, Next, Finish
  • Rightclick the new “All Windows 7 Systems”, click “Update Collection Membership”, rightclick again and click refresh. The Windows 7 systems should appear.

Use your imagination to create all sort of collections you might need. Like systems with 512MB ram or less, systems with de specific type of cdromdrive, anything you can imagine.

By the way: Windows 2008 R2 would be “%Server 6.1%” as value

Windows 2008R2 and SCCM 2007 SP2 - Pt3 - Basic configuration

After the previous article, the installation of SCCM 2007 SP2, it’s time to do the basic configuration.

Basic configuration, find clients on the network
Log on to the Configuration Manager Console

  • Expand (in order) site database, site management, <your site>, site settings, site systems, <your server> and on the right pane, rightclick “ConfigMgr management point” and properties. Select “Allow devices to use this management point” and click OK
  • Rightclick Boundaries, select New Boundary, add a description (e,g, “VL3 boundary” to match it with the sitecode of your installation) and set type to “Active Directory Site”. Then select the sitename that has been configured in Part 1 of this Windows 2008R2 and SCCM 2007 SP2 series, OK, OK
  • Rightclick your site (the one under site management) and click properties. Go to tab Advanced and make sure “Publish this site in Active Directory Domain Services” and “Publish the default management point in DNS (Intranet Only)” are selected. Press OK.
  • You have to define some sort of discovery method so that SCCM can find clients and/or servers (you can also select other methods but i’m going for “Active Directory System Discovery”). Go to Discovery Methods and rightclick “Active Directory System Discovery”, properties, select “enable ..” and click on the yellow icon that looks like a sun. Select ‘Local Domain” and make sure “Recursive” is enabled and press OK. In the window that opens select the topmost item which should be the name of your active directory domain (in my case: “tailspintoys”) and press OK and OK again.
    Goto the tab polling schedule and select “custom schedule” and recur every 5 minutes + OK.
    Press OK to save these settings and quit the window.
    Give SCCM some time to actually discover the computers. Then expand site database, computer management, collections, all systems. Rightclick on “all systems” and select “update collection membership”. Wait a little. Then rightclick again and select “refresh”. You should see some computers now, or at least your domain controller.

    Remember that you always have to “update collection membership” and then “refresh” to see new computers.

Push the sccm client to clients and servers

  • Expand (in order) site database, site management, <your site>, site settings, client installation methods.
  • Rightclick “Client Push Installation”, properties.
  • Click “enable client push installation…” and click on OK at the popup window.
  • Select servers, workstations and domain controllers and also “Enable client push installation to site systems”
  • On the tab accounts, click on the button that looks like a sun and specify the administrator account (best practice is that you will not use that in a production environment!!), OK, Apply, OK

Go back to your collection of computers, “update collection membership” and then “refresh” and after a while the table “Client” will say YES to indicate the SCCM client has been installed.

Create some reports
After the client has been pushed to all desired systems, you want to do something with the collected information.

  • Expand (in order) site database, site management, <your site>, site settings, site systems, <your server> and rightclick your server, select New Roles, Next, select “reporting point” + Next, Finish, Next, Close.
  • Expand (in order) site database, computer management, reporting, Reports and rightclick a desired report, e.g. “Computers in a specific workgroup or domain” and select Run.
  • Or rightclick Reports and select Run. A browser will open and you can click through all the reports. Cool uh?

Wednesday, August 3, 2011

Windows 2008R2 and SCCM 2007 SP2 - Pt2 - Install SCCM 2007 SP2

Continuing the previous article, once you have all the prerequisites in place, you are ready for the installation of SCCM 2007 SP2.

Extend the active directory schema
First, you have to extend the Active Directory Schema. The best way to do this is to log on to on the domain controller that holds the schema master role and start an elevated dos prompt. Then run the following program from the SCCM 2007 SP2 cd (or files on a share):

"\smssetup\bin\i386\extadsch.exe"

If you encounter errors like these:

<09-11-2010 17:53:11> Modifying Active Directory Schema - with SMS extensions.
<09-11-2010 17:53:11> DS Root:CN=Schema,CN=Configuration,DC=stpauls,DC=qld,DC=edu,DC=au
<09-11-2010 17:53:11> Failed to create attribute cn=MS-SMS-Site-Code.  Error code = 8224.
<09-11-2010 17:53:11> Failed to create attribute cn=mS-SMS-Assignment-Site-Code.  Error code = 8224.
...
<09-11-2010 17:53:12> Failed to extend the Active Directory schema.

.. you probably have some replication issues to deal with first. Or, in my case, the domain had one or more child domains and those domain controllers were offline. Make sure they are online and reachable.

Add the computer account to the System container

  • On the domaincontroller, start Active Directory Users and Computers.
  • Make sure you have advanced features enabled (View, Advanced Features)
  • Rightclick the “System” container, properties
  • Security, Add, Object Types, enable Computers + OK, type in your SCCM computername and click OK
  • Make sure your SCCM computername is selected, then click full control, followed by advanced
  • Locate your SCCM computeraccount, select it and click on Edit, set Apply to to “This Object and all descendant objects”, OK, OK

Install SCCM

  • From te splash screen run the “Run the prerequisite check”
  • If you’ve followed my previous article and you’ve installed SQL, enter your servername (my case: SCCM01) in the first two fields and press OK
  • Checks will run and if all goes well you’ll see “All required prerequisite tests have completed successfully”
  • On the splash screen click on “Install - Configuration Manager 2007 SP2”
  • Next, Next, I accept + Next, Custom Settings + Next, Primary Site + Next, Next, …. Next, Enter a (3 cypher/letter) site code and a description (”VL3” and “Test VLAN 3” in my case) for the site and on the next screen select Mixed Mode, unless you have a Public Key Infrastructure in place and configured for SCCM.
  • Keep all the rest of de settings default until you reach the “Updated Prerequisite Components” screen. Select the “Check for updates …” and click Next. Select a folder to download the updates (e.g. e:\downloads\) and hit Next. Some updates will be downloaded.
  • Once downloaded, you come to the Settings Summary. Press Next and another prerequisite check will run. If all goes well, press “Begin Install”.
  • Press Finish.
  • Reboot the computer and SCCM 2007 SP2 is ready for configuration

Windows 2008R2 and SCCM 2007 SP2 - Pt1 - Getting all the prerequisites right

I’ve been talking to some people about SCCM recently and it seems to be difficult to understand the whole process to set it up right. Therefore i’m going to share my experiences.
This first part covers all the prerequisites and setting them up.

1 - The (simple) setup

I’m going to presume an active directory is already present.
My (vmware) setup:

  • DC1
    • Windows 2008 R2 with SP1
    • 1vCPU, 512MB ram, 1×32GB harddisk (C:)
    • 10.10.10.100
    • role: the one and only domain controller responsible for the domain “tailspintoys.com”.
  • SCCM01
    • Clean installation with Windows 2008 R2 with SP1 added to the “tailspintoys.com” domain
    • 2vCPU, 2GB ram, 2×32GB harddisk (C: and E:, D: is the dvd player)
    • 10.10.10.125
    • role: going to be the SCCM 2007 SP2 server, also acting as SQL, WDS and IIS server. More on that later.

2 - Windows 2008R2 Roles, Features and configuration for SCCM

Features
On SCCM01, let’s add some features first. Start the server manager, go to features, add features:

  • select feature “background intellingend transfer service (BITS)”
    • yes, “Add Required Role Services”
  • select feature “remote differential compression”
  • next, next
  • since we’ve added the webserver role (that came with BITS) we now have the chance to add extra role services for this role. Add the following:
    • “Webdav Publishing”
    • “ASP .NET” (yes, add the dependencies)
    • ASP (you’ll need that for the reporting of SCCM, at first i forgot which led to “HTTP error 404.3 - Not Found” errors)
    • “Windows Authentication”
    • “IIS6 WMI Compatibility”
  • next, install, close

Configure webdav
Now we have to configure the webdav properties for the default website in IIS. You can do it later after SCCM is fully installed but you have to do it at some point so why not do it now.
Microsoft has a document on this but here it is in short:

  • Start the IIS manager
  • Expand till you see the default website. Click on it.
  • In the middle pane, doubleclick “Webdav Authoring Rules”
  • In the right pane, select “enable webdav”, followed by “Webdav Authoring Rules”, followed by “Add Authoring Rule”
  • “All Content”, “All Users”, “Read” + OK
  • In the right pane, select “Webdav Settings”
    • Allow anonymous property queries = True
    • Allow Custom Properties = False
    • Allow property queries with infinite depth = True
    • Allow hidden files to be listed = True
    • In the right pane, click Apply
  • Close the IIS manager

Roles
As SCCM needs WSUS and relies on the PXE server from WDS, we have to install some additional roles. Go to the server manager, roles and add the following role first. You have to install the WSUS role later, you can’t select it with other roles at the same time. So first:

  • Windows Deployment Services. Just next, next next, ….

Now add the following role:

  • Windows Server Update Services (yes, add the dependencies). Next, next, next, ….
  • If you are wondering why installation takes such a long time, notice the window on your taskbar. An additional screen with “Welcome to Windows Server Update Services 3.0 SP2 Setup Wizard” has opened.
    • I’ve placed the wsus data on E:\WSUS and i’m using the Windows internal database, but other circumstances may apply.
    • Click through the setup till the end and click Finish
  • When the roles are installed, click Close. A new window to configure WSUS will open.
  • Cancel these configuration steps.

Configure WDS

  • From the Administrative Tools, start Windows Deployment Services.
  • Expand servers, Rightclick SCCM01 and select Configure Server
  • I’m storing the data on E:\RemoteInstall but change to match your environment
  • I’m selecting “Respond to all client computers (Known and Unknown)” but that’s also a choice
  • Don’t select “Add images to the server now” and Finish

If you are not going to run DHCP on this server, skip this next 3 steps. But if you are going to install the DHCP role on this server then do the following prior to installing the DHCP role:

  • Rightclick the SCCM01 server and select Properties
  • Go to the tab DHCP
  • Select the first option “Do not listen on port 67”.

Optionally: Install and configure the DHCP role on this server
This is optional. You can run DHCP on any other server too.
But if you are installing DHCP on this server (i’m sure the basic configuration doesn’t need additional explaining here), all you have to do is go to the WDS settings (above) and on the DHCP tab select the “Configure DHCP option 60 …”. Then restart the DHCP service.

Configure DHCP that runs on a different server
If you are running DHCP on a different server in your network, configure options 66 with the ip-address of the WDS server and option 67 with “boot\x86\wdsnbp.com”. “wdsnbp.com” is a little utility that automatically determines the platform so it will automatically switch to x86 or x64 if neccessary.

At this point, all the Windows “internal” software related prerequisites on the SCCM01 server are in place.

3 - Other prerequisites

Associate a subnet with a site
To define a boundary for SCCM later, it is important to have a subnet defined and match it with a site in active directory.
So if you have not defined a subnet yet (if you have done a plain active directory installation, you won’t), then log on to the domain controller and do the following:

  • Open Active Directory Sites and Services
  • Expand till you see Subnets
  • On Subnets, rightclick and select “New Subnet”
  • Prefix: in my case: 10.10.10.0/24 and select a site object from the box below (on a plain installation it’s just Default-First-Site-Name)

Install SQL server for SCCM
To start with: i’m far from an expert on SQL. Beste practices may be different. But to get things up and running, the following will work.
SCCM won’t work on Express editions of SQL, so make sure you have a full version (get trial version here). I’ve read rumours that SCCM 2007 SP2 doesn’t work on SQL 2008 R2 but it does!

  • On the domain controller, start “Active Directory Users and Computers” and create a group called “SQL Admins” and make this group member of the group “Domain Admins”
  • Also create a new account called “sql2008r2”. Make this user member of the group “SQL Admins”
  • On the SCCM server, go to the server manager, add the feature “.NET Framework 3.5.1 Features” and add the required dependencies. Next, Install, Close
  • Reboot the server prior to installing SQL to be sure you don’t have pending installation tasks
  • Run setup.exe. On the first page, there’s a System Configuration Checker. Run it, all checks should be OK. If not, correct them
  • Click on Installation on the left side of the screen, then select “New installation …”
  • Keep everything default unless stated otherwise.
  • At “Setup Role”, choose “SQL Feature Installation”
  • Only the “Database Engine Service” is really required, but you also want to select “Reporting services” to create all kinds of cool reports from SCCM later. Also select “Management Tools - Complete”.
  • At “Server Configuration”, click on “use the same account for all services” and supply the “sql2008r2” account created in the second step.
  • At “Database Engine Configuration”, click “Add the current user” followed by “Add” and also add the “SQL Admins” group.
  • Complete the rest of the installation of SQL

Your system is now ready for the installation of SCCM 2007 SP2

Tuesday, July 19, 2011

Windows XP Audit mode

Maybe a bit late ….

Windows 7 offers a very handy feature called the Audit Mode. I’ve blogged about that before. This enables you to prepare the computer for the end-user, therefore it skips the whole OOBE (Out Of Box Experience) and the creation of local user accounts.
Windows XP does not have that feature so on the end of a fresh installation of Windows XP you’ll be prompted to create a user account and Windows will then automatically log in with that account. Microsoft doesn’t allow you to skip this, so you will always have to create a second local account (besides the Administrator account).

I recently found out a way to bypass this. Ok, resetting the machine does the trick also. But a more friendly way is to type SYSTEM in the first field.

Thursday, June 23, 2011

Windows 7 point and print / trusted printer dialog

(for mr Face ;-) )

Whereas point and print restrictions was a user policy for clients < Win7, as of Win7 it is a computer policy.
So to prevent installations prompts for printers:

  • Computer Configuration
  • Policies
  • Administrative Templates
  • Point and Print restrictions = Disabled

Monday, June 20, 2011

vbs loginscript actions based on ip range

Here’s an example:

On Error Resume Next

' #################################################
'Select the number of characters on the left that need to be checked
' Note the following situations:
'  10.150.9.    <-- check on charleft=9 including trailing "."!
'  10.150.10
'  10.150.11
' or
'  10.150.99.   <-- check on charleft=10 including trailing "."!
'  10.150.100
'  10.150.101
Const charleft = 10
' #################################################

Const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\" & ".\root\default:StdRegProv")
Set WSHShell = CreateObject("Wscript.Shell")
Set WSHNetwork = CreateObject("WScript.Network")
strKeyPath = "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces"

oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys

For Each subkey In arrSubKeys
    DHCPAddress = WSHShell.RegRead("HKLM" & strKeyPath & subkey & "\DhcpIPAddress")
	'Skip disconnected adapters and apipa addresses (failed dhcp)
	If DHCPAddress <> "0.0.0.0" And Left(DHCPAddress,3) <> "169" Then
		'wscript.echo "Interface " + subkey + " = " + DHCPAddress
		TestOctet1 = left(DHCPAddress, int(charleft))
		Select Case TestOctet1
			case "10.150.123"
			'location A with 1 ip range
			WScript.Echo "this is location A"
			'actions for location A
			WSHNetwork.AddWindowsPrinterConnection "\\printserver\main_printer_location_A"
			WSHNetwork.MapNetworkDrive "L:", "\\NT2000\data_location_A"

			case "10.150.99.","10.150.101"
			'location B with 2 ranges, note the first range with trailing "." because it's shorter
			WScript.Echo "this is location B"
			'actions for location A
			WSHNetwork.AddWindowsPrinterConnection "\\printserver\main_printer_location_B"
			WSHNetwork.MapNetworkDrive "L:", "\\NT2000\data_location_B"

			case "192.168.2","10.150.102","10.234.234"
			'location C with 3 ranges
			WScript.Echo "this is location C"
			'actions for location A
			WSHNetwork.AddWindowsPrinterConnection "\\printserver\main_printer_location_C"
			WSHNetwork.MapNetworkDrive "L:", "\\NT2000\data_location_C"

			case "10.22.164","10.22.165"
			'location D with 2 ranges
			WScript.Echo "this is location D"
			'actions for location A
			WSHNetwork.AddWindowsPrinterConnection "\\printserver\main_printer_location_D"
			WSHNetwork.MapNetworkDrive "L:", "\\NT2000\data_location_D"

		End Select
	End If
Next

Friday, May 20, 2011

Disable ipv6 and Teredo

To completely disable ipv6 and the Teredo interface:

reg add "HKLM\SYSTEM\CurrentControlSet\services\Tcpip6\Parameters" /v DisabledComponents /t REG_DWORD /d "255" /f

“255” decimal stands for 0×000000ff hexadecimal.
However, this isn’t listed here: http://support.microsoft.com/kb/929852/. Nonetheless this setting suits my needs best.

Thursday, May 12, 2011

VMWare Windows 2008 slow mouse performance

After installing the vmware tools on a Windows 2008 (R2) server, the mouse (still) performs very slow.

The solution is to update the video card driver.
Even after vmware tools installation, the vga card is listed as “Standard VGA Graphics Adapter”
Normally all drivers can be found at:

C:\Program Files\VMWare\VMWare Tools\Drivers\

However, the vga driver is located at:

C:\Program Files\Common Files\VMWare\Drivers\

Take the “wddm_video” folder.

A reboot is required. After that, you’ll be surprised :)
Increasing the virtual video RAM is supposed to increase performance even more.

Wednesday, May 11, 2011

Windows 7 set environment variables permanently

It’s not that hard to set environment variables for a current (dos) session.
But sometimes you want to set or update variables permanently, e.g. the Path variable.
Windows 7 has a nice built-in tool called “setx” to do these sort of things (and more).

setx /M PATH "%path%;c:\bla"

Where /m makes it system-wide instead of the current user.

Thursday, April 28, 2011

Windows 7 temporary profile after profile cleanup

After cleaning up a userprofile on a Windows 7 station (Deleting folders “c:\users\MyUserAccount” and the roaming profile on “\\fs01\profiles\MyUserAccount”) i thought i would start with a clean profile.
But Windows kept logging user “MyUserAccount” in with a temporary profile.

It seems that Windows keeps a list of profile locations in the registry. If that location for a certain user can’t be found, the user is logged on with a temporary profile.
This is the key:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

What you see there is a lists of profile SID’s, so you have to check them all out to find your user and delete the whole key accordingly.

I thought it would be handy to write a script that automates this.
It checks for a key called “ProfileImagePath” and if the value in that key (e.g. c:\users\JohnDoe) doesn’t exist on the local system, it wipes the whole registry key from the ProfileList.

Save as W7ProfileListCleanup.vbs:

ON ERROR RESUME NEXT

'### GLOBAL VARIABLES
Dim WSHShell, oFSO, strComputer, ProfileListRegistryLocation, ArrayWithProfileSIDS, Subkeys, HKEY_LOCAL_MACHINE

'### CREATE OBJECTS
Set WSHShell = CreateObject("WScript.Shell")
Set oFSO = CreateObject("Scripting.FileSystemObject")
strComputer = "."
Set objRegistry = GetObject("winmgmts:\" & strComputer & "\root\default:StdRegProv")

'### CONSTANTS
HKEY_LOCAL_MACHINE = &H80000002
ProfileListRegistryLocation = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
RegistryKeyContainingPath = "ProfileImagePath"

'### FUNCTIONS NEEDED
Function CheckAndDelete(LocalProfileDir, ProfileSID, FullPath)
  If not oFSO.FolderExists(LocalProfileDir) then
    WScript.Echo "NOT FOUND: " + LocalProfileDir
    DeleteProfileListKeyRecursive FullPath
  else
    WScript.Echo "OK:        " + LocalProfileDir
  end if
End Function

Function DeleteProfileListKeyRecursive(FullPath)
  WSHShell.Run "reg delete ""HKLM" + FullPath + """ /f", 0, True
  WScript.Echo "- Deleted: " + FullPath
End Function
'### END OF FUNCTIONS NEEDED

'### START THE ACTION

'### ENUMERATE THE LIST WITH PROFILES
objRegistry.EnumKey HKEY_LOCAL_MACHINE, ProfileListRegistryLocation, ArrayWithProfileSIDS

For Each ProfileSID In ArrayWithProfileSIDS
  FullPath = ProfileListRegistryLocation & "" & ProfileSID
  objRegistry.GetExpandedStringValue HKEY_LOCAL_MACHINE, FullPath, RegistryKeyContainingPath, LocalProfileDir
  '### CHECK FOR DIRS AND DELETE IF NOT FOUND
  CheckAndDelete LocalProfileDir, ProfileSID, FullPath
Next

Friday, April 22, 2011

Change Windows 7 logon background

Whether it’s just for fun or your company wants to brand their Windows 7 logon background, here’s how:

Prepare the system:

reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\Background" /v "OEMBackground" /t REG_DWORD /d "0x1" /f
mkdir c:\windows\system32\oobe\info\backgrounds

Now, at least place the following file in c:\windows\system32\oobe\info\backgrounds.

  • backgroundDefault.jpg

This will be the “fallback” image, so if none of the following files is found the image above will be stretched to fit your current resolution.

Optionally you can place the following files:

  • background768×1280.jpg
  • background900×1440.jpg
  • background960×1280.jpg
  • background1024×1280.jpg
  • background1280×1024.jpg
  • background1024×768.jpg
  • background1280×960.jpg
  • background1600×1200.jpg
  • background1440×900.jpg
  • background1920×1200.jpg
  • background1280×768.jpg
  • background1360×768.jpg

Remeber: file size cannot exceed 256 KB (so i’ve heard, not tested)….

Tuesday, April 12, 2011

icacls (win2k8) scripting examples

After cacls, xcacls.vbs, now we have icacls to set file and folder permissions.

Here are some practical examples.

Create a bunch of directories

md d:\apps
md d:\profiles
md d:\users

Share the directories. Note the offline caching; users are allowed to enable offline caching for their homedirs, other directories are disabled for offline caching.

net share apps=d:\apps /grant:everyone,FULL /CACHE:None
net share profiles=d:\profiles /grant:everyone,FULL /CACHE:None
net share users=d:\users /grant:everyone,FULL /CACHE:Manual

Now let’s script the ntfs permissions for the apps share:
- “(OI)(CI):F” means Full Control “This Folder, Subfolders and files”
- “(OI)(CI):M” means Modify “This Folder, Subfolders and files”
- “/inheritance:r” means remove all inherited ACL’s from parent

icacls "d:\apps" /grant "domain admins":(OI)(CI)F /inheritance:r
icacls "d:\apps" /grant "everyone":(OI)(CI)M /inheritance:r

On the profiles share, only the “domain admins” should be allowed to enter all “Folders, Subfolders and files” (hence the (OI)(CI):F) , everyone else should be able to to ready “this folder only”.
So without an combination of (CI) and/or (OI) it means “this folder only”

icacls "d:\profiles" /grant "domain admins":(OI)(CI)F /inheritance:r
icacls "d:\profiles" /grant "everyone":R /inheritance:r

Upon creating a new user, the Domain Admin should manually create a profile folder for the user and add the user with appropriate rights.

The same goes for the users share containing the homedirectories of all users

icacls "d:\users" /grant "domain admins":(OI)(CI)F /inheritance:r
icacls "d:\users" /grant "everyone":R /inheritance:r

Now use your own imagination :)

Friday, March 18, 2011

powershell - set disk quota using wmi

The 2003 powershell goes on :-)
Again, there are no available modules so i had to create my own.
How to set disk quota for a certain user (in megabytes) on a certain Windows 2003 server on a certain drive? Here’s how:

function set_disk_quota($username, $quota_hard, $computername, $disk)
{
  # preferred quota mode is enabled+deny access to disk, which is type 2
  # for logging purposes only but still allow disk access, select type 1
  $default_quota_mode = "2"

  $query_quota_enabled_or_not = "select * from Win32_QuotaSetting where VolumePath='"+$disk+":\\'"
  $query_user = "select * from Win32_Account where name='"+$username+"'"
  $query_disk = "select * from Win32_LogicalDisk where DeviceID='"+$disk+":'"

  $quota_disk = get-wmiobject -query $query_quota_enabled_or_not -computername $computername
  if ($quota_disk.State -eq "0")
  {
    echo "CHECK - ERROR - state 0 = Quota not enabled on disk -$disk- of -$computername-"
    echo "setting quota"
    $quota_disk.State = $default_quota_mode
    $quota_disk.Put()
  }
  if ($quota_disk.State -eq "1")
  {
    echo "CHECK - WARNING - state 1 = Quota enabled on disk -$disk- of -$computername- but not access is not denied when over quota"
    echo "setting quota"
    $quota_disk.State = $default_quota_mode
    $quota_disk.Put()    
  }
  if ($quota_disk.State -eq "2")
  {
    echo "CHECK - OK - state 2 = Quota enabled on disk -$disk- of -$computername- and access is denied when over quota"
  }

  $objAccount = get-wmiobject -query $query_user
  $objDisk = get-wmiobject -query $query_disk
  $objquota = (new-object management.managementclass Win32_DiskQuota).CreateInstance()
  $objquota.User = $objAccount.Path.RelativePath
  $objquota.QuotaVolume = $objDisk.Path.RelativePath

  if ($quota_hard -eq "0")
  {
    $objquota.Delete()
    echo "Quota deleted for $username"
  }
  else
  {
    $objquota.Limit = [int]$quota_hard * 1024 * 1024 * 1
    # Set the warning level to 90% of the $hard_limit
    $objquota.WarningLimit = [int]$quota_hard * 1024 * 1024 * 0.9
    $objquota.put()
  }  
}

Thursday, March 3, 2011

exchange 2003 powershell - forwarding

Because i need to maintain lots of Exchange 2003 servers and there are no Exchange 2003 powershell modules, i’m writing my own.
Here’s a piece of code that handles the forwarding of mail for users.
As you know, forwarding mail for a mailbox/user involves creating a contact with an external smtp address in Active Directory. Next, that contact can be assigned to the mailbox and a forwarding mode can be selected.
This script will handle all of those functions for you.

The script uses two global variables (customize to match your own Active Directory and/or place where you want to create these forwarding contacts):

$FQDN=",DC=netherlands,DC=europe,DC=microsoft,DC=com"
$base_security_groups_container="CN=Users"

Here’s the code:

function set_forward_mail($username, $forwarding_mode, $forwarding_address)
{
  # forwarding_mode
  # 0 = forwarding disabled
  # 1 = forward without local delivery
  # 2 = forward with local delivery

  if ($forwarding_mode -eq "2")
    {
      if (!(get-qadobject -identity "$username (forwarded by PowershellApp)"))
      {
        # contact doesn't exist (yet). Create now
        New-QADObject -ParentContainer "$base_security_groups_container$FQDN" -type "contact" -name "$username (forwarded by PowershellApp)" -DisplayName "$username (forwarded by PowershellApp)" -ObjectAttributes @{Description="$username (forwarded by PowershellApp)";mail="$forward_address";targetAddress="SMTP:$forwarding_address";mailNickname="$username"+"_forwarded_by_PowershellApp";msExchHideFromAddressLists=$true}
        # Recipient Update Service will do the rest.
        # Set the forwarding mode, type 2
        $forward_user_dn = (Get-QADObject -identity "$username (forwarded by PowershellApp)" | Select-Object dn).dn
        set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$true;altRecipient=$forward_user_dn}
      }
      else
      {
        # contact DOES exist. Update
        set-qadobject -identity "$username (forwarded by PowershellApp)" -ObjectAttributes @{Description="$username (forwarded by PowershellApp)";mail="$forward_address";targetAddress="SMTP:$forwarding_address";mailNickname="$username"+"_forwarded_by_PowershellApp";msExchHideFromAddressLists=$true}
        # clear any old addresses in the list of addresses and make the new one primary
        get-qadobject -identity "$username (forwarded by PowershellApp)" | Clear-QADProxyAddress | Add-QADProxyAddress -Address "SMTP:$forwarding_address" -Primary
        # make sure the forwarding mode is correct, type 2
        $forward_user_dn = (Get-QADObject -identity "$username (forwarded by PowershellApp)" | Select-Object dn).dn
        set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$true;altRecipient=$forward_user_dn}
      }
    }
  if ($forwarding_mode -eq "1")
    {
      if (!(get-qadobject -identity "$username (forwarded by PowershellApp)"))
      {
        # contact doesn't exist (yet). Create now
        New-QADObject -ParentContainer "$base_security_groups_container$FQDN" -type "contact" -name "$username (forwarded by PowershellApp)" -DisplayName "$username (forwarded by PowershellApp)" -ObjectAttributes @{Description="$username (forwarded by PowershellApp)";mail="$forward_address";targetAddress="SMTP:$forwarding_address";mailNickname="$username"+"_forwarded_by_PowershellApp";msExchHideFromAddressLists=$true}
        # Recipient Update Service will do the rest.
        # Set the forwarding mode, type 2
        $forward_user_dn = (Get-QADObject -identity "$username (forwarded by PowershellApp)" | Select-Object dn).dn
        set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$false;altRecipient=$forward_user_dn}
      }
      else
      {
        # contact DOES exist. Update
        set-qadobject -identity "$username (forwarded by PowershellApp)" -ObjectAttributes @{Description="$username (forwarded by PowershellApp)";mail="$forward_address";targetAddress="SMTP:$forwarding_address";mailNickname="$username"+"_forwarded_by_PowershellApp";msExchHideFromAddressLists=$true}
        # clear any old addresses in the list of addresses and make the new one primary
        get-qadobject -identity "$username (forwarded by PowershellApp)" | Clear-QADProxyAddress | Add-QADProxyAddress -Address "SMTP:$forwarding_address" -Primary
        # make sure the forwarding mode is correct, type 2
        $forward_user_dn = (Get-QADObject -identity "$username (forwarded by PowershellApp)" | Select-Object dn).dn
        set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$false;altRecipient=$forward_user_dn}
      }
    }
  if ($forwarding_mode -eq "0")
    {
      if (!(get-qadobject -identity "$username (forwarded by PowershellApp)"))
      {
        # contact doesn't exist, just disable forwarding
        set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$false;altRecipient=""}
      }
      else
      {
        # contact DOES exist. disable forwarding and delete contact
        set-qaduser -identity $username -objectAttributes @{deliverAndRedirect=$false;altRecipient=""}
        Remove-QADObject -identity "$username (forwarded by PowershellApp)" -Force
      }
    }
}

Wednesday, March 2, 2011

VBS detect type of computer (using WMI)

Because of some issue between Windows XP and a HP 6000 Pro system, i needed to rollout a script to ~10000 clients that detected the type of system and change the boot.ini accordingly.
Microsoft’s article on this “bug”.

' Quick'n Dirty HP 6000 Pro boot.ini (/usepmtimer) changer (c) Hugo

On Error Resume Next

Set objFSO = CreateObject("Scripting.FilesystemObject")
Set objShell = CreateObject("WScript.Shell")
Set objNetwork = CreateObject("WScript.Network")
Set WSHProcessEnvironment = objShell.Environment("Process")

strComputerName = "."
strWinMgt = "winmgmts://" & strComputerName &""

Set ComputerSystemSet = GetObject(strWinMgt).ExecQuery("select * from Win32_ComputerSystem")
For Each objComputerSystem In ComputerSystemSet
  strComputerSystem_Model = objComputerSystem.Model
  strComputerSystem_Description = objComputerSystem.Description
Next

WScript.Echo " Found: " + strComputerSystem_Model

' Learned so far:
' - "HP Compaq 6000 Pro MT PC"
' - "HP Compaq 6000 Pro SFF PC"
' - "HP Compaq 6000 Small Form Factor"
' - ..

Select Case strComputerSystem_Model
Case "HP Compaq 6000 Pro MT PC"
	boot_ini_aanpassen()
Case "HP Compaq 6000 Pro SFF PC"
	boot_ini_aanpassen()
Case "HP Compaq 6000 Small Form Factor"
	boot_ini_aanpassen()
Case "blablabla pro 6000 type 4 that will be found some day or the next"
	boot_ini_aanpassen()
Case Else
	WScript.Echo " No Pro 6000 detected, exit ..."
End Select

'#########################################################################
'  support function(s)
'#########################################################################

Function boot_ini_aanpassen()
    WScript.Echo " Match found, now change boot.ini"

    ' make the file accessable
    objShell.Run "c:\windows\system32\attrib.exe -h -a -r -s c:\boot.ini"

    ' sleep for a while because it needs time to process the attribute change (10 sec will do for sure)
    WScript.Sleep(10000)

    ' define new boot.ini layout
    strMyBootIni_line1 = "[boot loader]"
    strMyBootIni_line2 = "timeout=30"
    strMyBootIni_line3 = "default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS"
    strMyBootIni_line4 = "[operating systems]"
    strMyBootIni_line5 = "multi(0)disk(0)rdisk(0)partition(1)\WINDOWS=""Microsoft Windows XP Professional"" /fastdetect /usepmtimer"

    Const WriteMode = 2 '2 = ForWrite, 8 = ForAppend
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objTextFile = objFSO.OpenTextFile ("c:\boot.ini", WriteMode, True)
	  objTextFile.WriteLine(strMyBootIni_line1)
	  objTextFile.WriteLine(strMyBootIni_line2)
	  objTextFile.WriteLine(strMyBootIni_line3)
	  objTextFile.WriteLine(strMyBootIni_line4)
	  objTextFile.WriteLine(strMyBootIni_line5)
    objTextFile.Close

    ' re-attribute the file
    objShell.Run "c:\windows\system32\attrib.exe +h +a +r +s c:\boot.ini"

    WScript.Echo " Boot.ini changed. Active after next reboot"
End Function

Tuesday, March 1, 2011

Quick Sound Switch

One of those fine freeware utilities i have to remember: http://www.quicksoundswitch.toflo.de/eng/index.html

This comes in handy if you have multiple audio cards (e.g. normal audio card and audio over HDMI) and you want to quickly switch between primary output device.

Local mirror of version 2.11 in case the original site ever goes down: QuickSoundSwitch version 2.11

Friday, February 18, 2011

(image based) Windows 7 deployment a-z

As i promised to some folks, i’d publish my howto on how to deploy Windows 7. In this howto, i’m using image based distribution.

Essentials:

  • vm or physical machine
  • Windows 7 dvd
  • Windows® Automated Installation Kit (AIK) (download here and mind your language)

Here we go

  • Boot the machine from the Windows 7 dvd
  • Due to our fast deploy method, i’m not interested in the recovery partition. If a system fails, i’m simply going to deploy it again. Also i don’t need to encrypt the who diks with bitlocker. And last but not least, this keeps the partition structure easy. Therefore this is the time to create the partition structure manually before Windows does it for you and creates the first 100MB partition.
    So: on the screen where you can select your language and keyboard, press SHIFT+F10
  • A dos prompt opens, type
    • diskpart
    • list disk
    • select disk 0
    • create partition primary
    • select partition 1
    • format fs=ntfs quick
    • exit
    • exit
  • Now resume installation as normal, but choose “disk 0, partition 1” when selecting a destination
  • Rest of the installation goes automatically
  • At the point where you are prompted for a username, press CTRL+SHIFT+F3. This is called Audit mode. The system will reboot and log in automatically. It will continue to do this untill you sysprep the system. This gives you the chance to “Microsoft Update” your system and put other applications into the installation.
  • As said before, this is the chance to update your system with everything you want, like applications of your choice or Microsoft Updates. Reboot as many times as you want. Press cancel on the sysprep application after every logon. We’re not going to use the GUI anyway.
  • In the meanwhile, install de Windows® Automated Installation Kit (AIK) on another system.
  • Select an installation source (the dvd) and create a new answer file
  • As you can see, the sysprep stages consist of 7 stages now, but as we’re dealing with image based distribution and have allready processed the Audit stage manually, we’re only interested in 2 stages: Specialize and oobeSystem (Out Of Box Experience). This is important to know. More on these stages can be found at Microsoft’s website.
  • There are a lot of things you can do during all the stages, but i’m going to explain the essentials to make the installation after deployment run really unattended
  • Specialize:
    • Microsoft-Windows-Shell-Setup_neutral: Specify at least the Product Key and ComputerName. CopyProfile=True if you are doing weird things with your profile that needs to be inherited by the Default User profile.
    • Microsoft-Windows-UnattendedJoin_neutral: Specify the domain that needs to be joined, and one level deeper specify the credentials
  • oobeSystem:
    • Microsoft-Windows-International-Core_neutral: Specify the inputlocale, systemlocale and userlocale of your choice.
    • Microsoft-Windows-Shell-Setup_neutral: Specify Registered Owner, Registered Organization, TimeZone (F1 for explanation) and one level deeper:
      • Autologon: count 1, and supply the credentials (and domain if needed)
      • LogonCommands: this is one of the interesting things. I always try to keep the image itself as plain as possible. Instead i’m doing a “postinstallation” of some utilities. I’m calling these by the script i’m calling here. So “AsynchronousCommand(Order=1): CommandLine=C:\w7startup.bat, order=1, requires user input=False, Action=AddListItem
      • OOBE: HideEULAPage=True, HideWirelessSetupInOOBE=True, NetworkLocation=Work, ProtectYourPC=1
      • UserAccounts: Now this is the tricky one. You have to specify at least SOME action here or your unattended installation won’t be unattended and asks for some input in this stage. Create a local account or if that’s unacceptable do something irrelevant like add “Domain Admins” to your local “Administrators” group.
  • Now save your answer file and call it sysprep.xml
  • Place this file on the system you’ve installed in c:\Windows\system32\sysprep\
  • Open a dosprompt, go to the above directory and execute
    Sysprep.exe /generalize /oobe /shutdown /unattend:c:\Windows\system32\sysprep\sysprep.xml
    
  • The system will shutdown, then capture an image (can be a ghost image, drivesnapshot (very nice tool) image, Microsoft’s own imagex, etc)
    from this installation
  • Your unattended installation is ready.

How to deploy?
There are very cool ways to automate all these steps but these are the basics:

  • Place the image back onto a different pc
  • Copy a simple batchfile called “w7startup.bat” to the harddisk/partition that has just been filled. Simple example:
    @echo off
    IF NOT EXIST C:\Install\vmtools\setup.exe GOTO SKIPVMTOOLS
    echo - vmware tools detected
    start /wait C:\Install\vmtools\setup.exe /s /v"REBOOT=R /qb"
    :SKIPVMTOOLS
    echo - default login domain
    reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultDomainName /t REG_SZ /d "YOURDOMAIN" /f
    echo - disable uac
    reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLUA /t REG_DWORD /d 0 /f
    echo - activate current license key
    start /wait slmgr.vbs /ato //B
    echo - disable hybernate
    powercfg -h off
    echo - set powerscheme
    powercfg -S 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c
    echo - java
    start /wait c:\install\java\jre-6u23-windows-i586-s.exe /s /v/qn
    reg add "HKLM\Software\JavaSoft\Java Update\Policy" /v EnableJavaUpdate /t REG_DWORD /d 0x0 /f
    echo all installs done
    del /f c:\w7startup.bat
    
  • Don’t forget to delete w7startup.bat (”yourself”) at the end of the file, otherwise this file will run on every logon in the future. (or delete the HKLM\Software\Microsoft\Windows\CurrentVersion\Run\Unattend* registry key)
  • Copy all the recent versions of the installation files to the right directories so that your w7startup.bat will pick them up.

That’s it. That wasn’t that hard was it?

Some more on the underlaying techniques:
You don’t want to create an answer file for every pc.
In Windows XP, if you used c:\sysprep\sysprep.inf while creating your sysprepped pc, after deployment you could change values like e.g. the COMPUTERNAME=”" to a different name and the unattended installation would pick that up.
That won’t work with Windows 7 anymore (considering you’ve used c:\windows\system32\sysprep\sysprep.xml).
What sysprep actually does is create a file called C:\Windows\Panther\Unattend.xml based on the sysprep you’ve created. So that’s pretty interesting.
After you’ve deployed your image and you copy the w7startup.bat file and the other installation files, why not edit the C:\Windows\Panther\Unattend.xml file and replace values like:

<ComputerName>SYSPREPMACHINE</ComputerName>

or change the license key

<ProductKey>AAAAA-THISC-OMPUT-ERSOW-NKEY1</ProductKey>

or if you want a different domain to join:

<Domain>DIFFERENTDOMAIN</Domain>
<Password>differentpass</Password>
<Username>differentjoinuser</Username>

Wednesday, February 2, 2011

fat32 to ntfs conversion memory requirements

We’re currently rolling out huge ammounts of workstations.
The base-image is FAT32 so at first boot, the partition is converted to NTFS.
Our monitoring system noticed 6 clients (out of currently ~8000) failed and were still FAT32.

I can’t find the exact memory requirements but here’s a guideline based on experience:
Disks >123 GB will fail on 512MB of RAM, upgrade to at least 1GB
Disks >54 GB will fail on 256MB of RAM, upgrade to at least 512MB

Thanx to Thuur for his work

Tuesday, January 4, 2011

Group policy reporting

If you want to know what policies are processed, how long it takes, why certain objects can’t be found etc etc, use this great app: http://www.sysprosoft.com/policyreporter.shtml

My mirror (since site is slow and sometimes down): Policy_Reporter4_2.msi

Please enable enviroment logging first, see roaming profiles and logging

Monday, January 3, 2011

latest (portable) build of Chrome

Always the latest build:
Chromium download

Wednesday, December 22, 2010

exchange 2003 powershell - create mailbox

As i told before, it’s not that easy to make changes with powershell to your Exchange 2003 environment as it is nowadays with Exchange 2010.
Since it was pretty hard to read certain values from Active Directory, i’m doing a pretty nasty trick: copy the values from an existing user.

Here’s how to create a mailbox for an existing user:

function add_exchange2003_mailbox_for_user($username)
{
  # to keep it simple: let's copy the properties of a template user, e.g. Administrator, and create the mailboxes in the same database
  $template_user = "Administrator"
  $userproperties = get-qaduser -identity $template_user -IncludeAllProperties
  set-qaduser -identity $username -objectAttributes @{msExchHomeServerName=$userproperties.MsExchHomeServerName}
  set-qaduser -identity $username -objectAttributes @{mailnickname="$username"}
  set-qaduser -identity $username -objectAttributes @{mDBUseDefaults='TRUE'}
  set-qaduser -identity $username -objectAttributes @{homeMBD=$userproperties.homeMDB}
  # now the Recipient Update Service will do the rest ...
}

exchange 2003 powershell - add primary address

When you’re making changes to your active directory or exchange environment with powershell, it’s a piece of cake with Windows 2008 R2 and/or Exchange 2010. All the cmdlets are there by default.
But when you’re dealing with Windows 2003 and/or Exchange 2003, it’s a whole different story.
I will be posting some of my scripts for Windows 2003 and Exchange 2003 from now on.
Because Windows 2003 has no active directory powershell module, i’m using the Quest AD Templates for that purpose (highly recommended!).

Here’s how to change the primary address for an exchange 2003 user:

function set_exchange2003_primary_address($username, $primary_smtp_address)
{
  # lowercase the to-be-added address
  $primary_smtp_address = $primary_smtp_address.ToLower()
  
  # get current addresses
  $userinfo = get-qaduser -identity $username
  $new_proxyaddresses = $userinfo.ProxyAddresses

  # lowercase all the "SMTP:" entries
  foreach ($number in 0..($new_proxyaddresses.Count - 1) )
  {
    $address = $new_proxyaddresses[$number]
    $new_proxyaddresses[$number]=$address.Replace("SMTP:", "smtp:")
  }
  
  # Next, check if the to-be-added address is allready in the list
  $allready_in_list = $FALSE
  foreach ($number in 0..($new_proxyaddresses.Count - 1) )
  {
    $address = $new_proxyaddresses[$number].ToLower()
    $check = $address.CompareTo("smtp:$primary_smtp_address")
    if ($check -eq 0)
    {
      # address is found in the list. Make it PRIMARY
      $new_proxyaddresses[$number]=$address.Replace("smtp:", "SMTP:")
      $allready_in_list = $TRUE
    }
  }  
  # But if it's not found, add the new adress to the list as primary
  if ($allready_in_list -eq $FALSE)
  {
    $new_proxyaddresses += 'SMTP:'+$primary_smtp_address
  }

  # now write the addresses to active directory
  set-qaduser -identity $username -objectAttributes @{ProxyAddresses=$new_proxyaddresses}
}

Hmm..
Guess I should have payed more attention… Why not do this:

function set_exchange2003_primary_address($username, $primary_smtp_address)
{
  get-qaduser -identity $username | Add-QADProxyAddress -Address $primary_smtp_address -Primary
}

Monday, December 20, 2010

Bootvis

If you know what it is and (also) looking for it: Bootvis