Wednesday, April 27, 2011

Exchange 2010 SP1 anonymous relay

A common usecase for the need of open relays are MFC’s (”Copiers”) because people need to scan documents and want to mail them directly to recipients on the internet.

Never apply the following to your normal connector for mailflow, as your mailserver will most certainly be used to send spam!

Create a new receive connector (Server configuration, Hub Transport) and make sure it’s bindings don’t conflict with other connectors. The name for the connector could be something like “Relay Connector MFC’s” and make sure you add the right ip-addresses or ranges.
To grant the relay access, the following line will do the trick:

Get-ReceiveConnector "Relay Connector MFC's" | Add-ADPermission -User "NT AUTHORITY\ANONYMOUS LOGON" -ExtendedRights "Ms-Exch-SMTP-Accept-Any-Recipient"

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()
  }  
}

Wednesday, March 16, 2011

dmesg timestamps

To translate the timestamps in your dmesg into human readable timestamps, use the following perl script:

#!/usr/bin/perl

$uptime = `cat /proc/uptime | awk '{print $1}';`;
$boot = time() - $uptime;
chomp $boot;
while (<STDIN>) {
        if ($_ =~ /^\[([\s\d\.]+)\]/) {
                $time_offset = $1;
        }
        $real_time = sprintf scalar localtime($boot + $time_offset);
        $_ =~ s/\[[\s\d\.]+\]/\[$real_time\]/;
        print $_;
}

e.g.

[    9.815650] 3w-9xxx: scsi2: ERROR: (0x03:0x0101): Invalid command opcode:opcode=0x85.

will be translated into

[Wed Mar 16 16:02:32 2011] 3w-9xxx: scsi2: ERROR: (0x03:0x0101): Invalid command opcode:opcode=0x85.

Syntax:

dmesg | perl /root/print_time_offset.pl

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

Friday, November 12, 2010

areca use extra space after swapping hd’s

Say you have a raid5 volume of 3×500GB disks with an effective space of ~1TB.
You plug out 1 disk, swap it with a 1TB disk and let the areca rebuild the array.
You do the same for disk 2 and 3.
You’d probably think you’ll have an extra TB to use. But the areca won’t show you. Here’s how (undocumented feature):

  1. Login the browser management console (Raidset Functions > Rescue RaidSet)
  2. Enter the keyword “RESETCAPACITY Raid Set # 000”, confirm and submit. After that, controller will reconfigure the raidset capacity.
  3. Create an extra logical drive on the raidset

Thursday, November 11, 2010

renew a self-signed ssl certificate on exchange 2007

To renew a self-signed ssl certificate on an Exchange 2007 server:

Start the Exchange Management Shell, then:

Get-ExchangeCertificate -DomainName CAS01.contoso.com

Find the certificate that contains a “W” from the list of certificates For example, select IP.WS. The “W” indicates that the certificate is assigned to IIS.
Then to clone the certificate, run the following cmdlet (the thumbprint is unique):

Get-ExchangeCertificate -Thumbprint c4248cd7065c87cb942d60f7293feb7d533a4afc | New-ExchangeCertificate

The new cloned certificate will then be stamped with a new expiration date one year after the date you run the cmdlet.

And last but not least: assign the certificate to a service:

Enable-ExchangeCertificate -Thumbprint c4248cd7065c87cb942d60f7293feb7d533a4afc -Service IIS

Tuesday, November 9, 2010

rescan scsi bus without rebooting

If you attach an extra harddisk to your virtual machine and you don’t want to reboot, all you need to do is rescan your scsi bus.

First determine how many scsi adapters your system has:

# ls /sys/class/scsi_host
host0

Then order the rescan command to the adapter:

# echo "- - -" > /sys/class/scsi_host/host0/scan

Check your dmesg or /proc/partitions!

Monday, November 8, 2010

find LVM volumes

I needed to make a backup of an old server. So i booted an Ubuntu live cd. Then:

cat /proc/partitions

But I wasn’t able to mount certain partitions. It appeared to be lvm volumes.
To mount them, you’ll need the lvm2 package first.

sudo -s
apt-get update
apt-get install lvm2

Then find the volumes.

vgchange -a y
  3 logical volume(s) in volume group "VolGroup00" now active

Now look in your device mapper:

ls /dev/mapper/

.. and do whatever you like with it. In my case:

mkdir /mnt/vol00
mkdir /mnt/vol01
mkdir /mnt/vol02
mount /dev/mapper/VolGroup00-LogVol00 /mnt/vol00
mount /dev/mapper/VolGroup00-LogVol01 /mnt/vol01
  /dev/mapper/VolGroup00-LogVol01 looks like swapspace - not mounted
root@ubuntu:~# mount /dev/mapper/VolGroup00-LogVol02 /mnt/vol02

apt-get install smbfs
mkdir /mnt/targetserver/
smbmount //10.2.18.224/software /mnt/targetserver/
mkdir /mnt/targetserver/serverbackup/

cd /mnt
rsync -av vol00 vol02 /mnt/targetserver/

Tuesday, November 2, 2010

Log all output to a file (dos, bash)

I’m always googling for this. What was that thing again that logs all output to a file?

2>&1

Bash example:

root@ubuntu:/mnt/sda6# rsync -av * /mnt/backup/sda6/ >/mnt/backup/readrrors.txt 2>&1

Dos example:

copy backup.log \\nas\share\weeklog.txt >output.txt 2>&1

Monday, November 1, 2010

Export .pst files in Exchange 2010 SP1

In addition to the import procedures, here’s how to export to .pst files:

Add an import to the queue:

New-MailboxExportRequest -Mailbox p.puk -FilePath "\\FS01\data\Backup Mailbox (PST)\p.puk.pst"

And status:

Get-MailboxExportRequest

Paste as plain text

Have you ever copied some text from a web page or a document and then wanted to paste it as simple text into another application without getting all the formatting from the original source? PureText makes this simple by adding a new Windows hot-key (default is WINDOWS+V) that allows you to paste text to any application without formatting.

Download this 13KB utility here!

Friday, October 29, 2010

Import .pst files in Exchange 2010 SP1

SP1 for Exchange 2010 has a new approach for importing .pst files.
First of all make sure the group “Exchange Trusted Subsystem” has NTFS permissions on the folder which contains all the .pst files.
Second, make sure this folder has been shared. Exchange only accepts unc paths.
Third, you have to make a new role assignment to a security group.
Create a universal group called “Mailbox Import Export Access” in active directory and add the user who’s going to do the export. Next, from the Exchange Management Shell:

New-ManagementRoleAssignment -Name "Mailbox Import Export Access" -SecurityGroup "Mailbox Import Export Access" -Role "Mailbox Import Export"

All the preparations have been made.

To queue (yes queue!) the import for a user:

New-MailboxImportRequest -Mailbox p.puk -FilePath "\\FS01\data\Backup Mailbox (PST)\p.puk.pst"

You can repeat the line for other users or pipe a list of users to build a bigger queue.

The following command shows the queue and the status of all imports:

Get-MailboxImportRequest

or

get-mailboximportrequest | fl filepath,status

One drawback so far:
I haven’t been able to find a way to set the locale by default (was possible with non-SP1 by typing

-locale "nl-NL"

for Dutch users) which is really annoying since users will end up with “Inbox” instead of “Postvak In”, “Sent Items” instead of “Verzonden Items”, etc.
This can be overcome by logging in to the webmail before starting the import and set the default language from there (first question asked when logging in). But that’s still annoying.

Update 2011/03/25
I haven’t been able to test it yet but running the following command prior to the import might do the trick ….

Set-MailboxRegionalConfiguration p.puk -Language "nl-NL" -DateFormat "dd-MM-yyyy" -LocalizeDefaultFolderName:$true

or for all mailboxes

get-mailbox | set-mailboxregionalconfiguration -Language nl-NL -DateFormat "dd-MM-yyyy" -LocalizeDefaultFolderName:$true

Wednesday, October 27, 2010

Change domain admin password (without AD restore mode)

Today i needed access to a domain of servers, but one of our competitors would not provide us with the Administrator password, so i needed other ways to get in.

Petri.co.il has a nice page on that subject that consists of 2 steps:

  1. change the local administrator password (so you can boot into Active Directory restore mode)
  2. install a service to change the domain password

Somehow step 1 lead me to corrupt SAM/Software/system files so after restoring the original files i figured a way to skip that.

All you need is a Windows live cd or usb stick and the zipfile below. BartPE will do. Or use a commercial product like Active@ Boot Disk, which is really nice because of the fact that it’s based on a Vista kernel which supports the loading of drivers without rebooting. So you’re able to load drivers for raidcontrollers or other devices and your drives will appear directly.
Download this file and put it on a usb stick.

Now here we go:

  1. Boot your Windows live environment.

  2. Extract the content of the zip-file to c:\.
    You’ll have 2 directories.
    C:\RegEditPE
    C:\srvany

  3. VERY IMPORTANT: make a copy of your c:\windows\system32\config now. Just copy the entire directory to some location.

  4. Start C:\RegEditPE\RegEditPE.exe and after it’s done browse to HKEY_LOCAL_MACHINE.
    You’ll see new hives for windows installations that have been found, e.g. “SYSTEM_ON_G”.

  5. Edit C:\srvany\_service.reg and replace (ctrl+h) “SYSTEM_ON_E” with the one on your system.

  6. Check the line that says:

    "AppParameters"="/k net user Administrator 123456abc /domain"
    

    As you can see the password will be changed to “123456abc” but keep in mind that your domain can have complexity policies! Change to something more complex if needed!

  7. Save the file.

  8. Now doubleclick the file to merge it into the registry and close RegEditPE.

  9. I’ve provided cmd.exe from Windows 2003 SP2 in the zipfile, but you might want to do:

    copy x:\windows\system32\cmd.exe x:\srvany\
    

    (where x is your drive with your Windows installation.

  10. Reboot and wait a little. Now you can log in with your new password.

Tested on Windows 2003 SP2

Thursday, October 14, 2010

Forcing a refresh of Network Printer Settings from Print Server

If you have a printserver in your network and you want to change certain properties, e.g. print black/white instead of color, normally what you do is change the settings on the Advanced Tab - Default Settings Button. These are the settings a user inherits when first connecting to the shared printer.
But what if you want to revert these settings. You’d have to remove the printer from the userprofile and make sure the printer’s readded, in order to inherit the new default settings.

This is exactly what the following script does.
It also cleans removed/unshared printers, as it can only re-add printers that still exist.

on error resume next
Set WshNetwork = WScript.CreateObject("WScript.Network")

'## Enumerate all the current printers in the profile
Set oPrinters = WshNetwork.EnumPrinterConnections

For i = 0 to oPrinters.Count - 1 Step 2

'## Disconnect the printer
WshNetwork.RemovePrinterConnection ""& oPrinters.Item(i+1) &"", true, true
'## Readd the same printer (if still exists)
WshNetwork.AddWindowsPrinterConnection ""& oPrinters.Item(i+1) &"", true, true

Next

msgbox "Done"

You might want to comment the last line to make the script run totally silent.