I recently installed the posh4appv snapin to my AppV 4.6 Management server to script package installation and manipulation because we are going to be moving to a phase where we need less manual management of the console.
While installing it I ran across an error whenever I tried to run it:
PS C:\Users\svc_test> Get-AppVAdministrators
Get-AppVAdministrators : Object reference not set to an instance of an object.
At line:1 char:23
+ Get-AppVAdministrators <<<<
+ CategoryInfo : NotSpecified: (:) [Get-AppVAdministrators], NullReferenceException
+ FullyQualifiedErrorId : System.NullReferenceException,AppVSnapIn.GetAdministrators
I ran a procmon on this and traced on PowerShell.exe and it told me I was missing the "HKLM\SOFTWARE\Wow6432Node\Microsoft\SoftGrid\4.5\Server\SQLServerName" registry key. I added that key as a REG_SZ and the value being our SQL server name. I then tried to run the command about again and it failed again, but this time it reported the SQLDatabaseName registry key was missing. I added that to the registry and then tried again. It gave me one last fail.
This time on SOFTGRID_CONTENT_DIR. I added that key as a REG_SZ with the appropriate value and then I tried to run my command again. Low and behold it now works!
Wednesday, December 12, 2012
Saturday, November 17, 2012
Windows 8 iSCSI
iSCSI and Windows 8 changes
It appears Windows 8 has removed the CriticalDeviceDatabase key. Or, it looks like it just moved it to HKLM\System\ControlSet001\Control\DeviceLocations. Under the old CDD key there was thousands of listings of hardware ID's that were useless. It appears they just eliminated them and then renamed CDD to DeviceLocations.
There you go.
It appears Windows 8 has removed the CriticalDeviceDatabase key. Or, it looks like it just moved it to HKLM\System\ControlSet001\Control\DeviceLocations. Under the old CDD key there was thousands of listings of hardware ID's that were useless. It appears they just eliminated them and then renamed CDD to DeviceLocations.
There you go.
Wednesday, November 14, 2012
iSCSI, iPXE, Microsoft iSCSI Software Target, Microsoft DHCP
I was recently struggling to get iSCSI working for myself. Here were my problems and how I eventually fixed them.
To get iSCSI working the first thing I did was install the Microsoft Software Target 3.3 on a server machine. It's pretty simple. Go to iSCSI Targets and create a new target. Whatever you name it will be on the IQN so I've kept it short. The iSCSI Initators Identifiers is like MAC Address filtering for a DHCP server, if you don't match you can't connect to the iSCSI target. So set the SII to whatever IP, MAC Address or IQN you plan on using. If you're like me and wasn't sure what the IQN will be set to, preferring to have iPXE's generated one; the Windows event viewer Application log will tell you what the IQN is when it fails to connect. Look for Event ID 22.
When you are done creating the target you need to create the Virtual Disk (VHD) for the target. Right-click on the target and go "Create Virtual Disk for iSCSI Target" and follow the prompts until you have your vDisk associated with the target.
We are now done on the server side. To test the connection I launched iSCSI initiator on the same server and tried to connect to the iSCSI Software Target. It had a "Target Error" as the error message. To get around this I enabled loopback.
HKLM\Software\Microsoft\iSCSI Target
Value Name: AllowLoopBack
Type: REG_DWORD
Value: 1 (Default is 0)
This will enable you to connect to your iSCSI target.
I could now connect to the iSCSI target that resided on the same server and validate the software target was working correctly.
Now to get the client side working. My goal with this is to PXE boot some client machines with differencing VHD's off a golden Windows 7 image. I encountered numerous issues attempting to do this and I'll share with you my problems and how I solved them.
The first thing I did was configure PXE booting off the Microsoft DHCP server. I was going to make it launch PXELinux prior to iPXE and may modify my DHCP to do so in the future, but below is a screenshot of my working settings:
When I was trying to get PXELinux working with iPXE I ran into numerous problems. Before I get too far ahead here, this was my PXELinux default config file:
# These default options can be changed in the geniso script
SAY iPXE ISO boot image
TIMEOUT 30
DEFAULT ipxe.lkrn
LABEL ipxe.lkrn
KERNEL ipxe.krn
INITRD ipxe.ipxe
#!ipxe
dhcp
set keep-san 1
sanhook --drive 0x80 iscsi:192.168.1.2::::iqn.1991-05.com.microsoft:aclgdc01-t1-target
sanboot --nodescribe --drive 0xe0 http://192.168.1.2/win7/winpe.iso
PXELinux was booting the iPXE kernel, The iSCSI target wasn't detected natively by the Windows 7/2008 DVD's (which everything I read said that it should be). To correct this I made a modified WinPE with the iSCSI Initiator builtin. When I booted up that WinPE I could start the MSISCSI service and connect to the target. I thought things looked good and I could format the target and make folders/files on it. I could even bootsect it. I then mapped a network drive to the Windows installer files (which iPXE recommends) then ran setup.exe. I got to the part where I could choose the hard disk but Windows wouldn't let me install on it giving me an error message.
"Windows cannot be installed to Disk <#> Partition <#>. (Show details)" -> "Windows cannot be installed to this disk. iSCSI deployment is disabled since no NICs referenced in the iBFT can be resolved to actual NT-visible devices. Windows cannot be installed to this disk. This computer's hardware may not support booting to this disk.
Alright, at least I was making progress. From here I had to find out what a iBFT was and why can't Windows resolve it when I'm staring straight at the hard disk. The importance of it is found here.
"When the pre-boot loader starts, it loads a real-mode network stack driver. The loader contains an iSCSI initiator which logs on to the iSCSI target and mount the boot disk to the system. Another function of the loader is to populate the iSCSI Boot Firmware Table (iBFT), which is required for iSCSI boot. The Boot Parameter driver in Windows will load the parameters from the iBFT, and the Microsoft iSCSI Software Initiator will be able to connect to the iSCSI target using the parameters set in the iBFT. The importance of the iBFT is to be able to share the parameters between the iSCSI boot initiator (which establishes the session in the preboot phase) and the Microsoft iSCSI initiator (which establish the session after Windows boots)."
So my iPXE isn't storing it's values in the iBFT. This seemed weird to me because I could see it preserving the connection when I booted. Everything I read said the "set keep-san 1" is the magic to storing the iPXE values in the iBFT.
So it appeared to be working and I thought maybe it's Hyper-V. I read other people using Hyper-V were able to get this to work, but I'm stumped. It won't work for me. So I tried VMWare Player. I had the same issue there. No NICs referenced in the iBFT even though I could use the MS Initiator to connect to the target.
At this point I was getting pretty frustrated. For all intent and purposes this should work. So I went back to ipxe.org and read their Windows Deployment Service guide and setup WDS and made a WDS wim thinking maybe it had some magic touch; even though I had read that the standard install media should work.
Well, the WDS image didn't work either. At this point I went back to ipxe.org and followed their PXE Chainloading guide exactly. Well, mostly exactly. I didn't want to make a reservation so I applied the setting across the entire DHCP by entering everything in Server Options (see the first screenshot of this post).
Like magic, as soon as I changed the kernel from iPXE.KRN to undionly.kpxe it showed me something different on the Hyper-V console:
Like Magic the undionly.kpxe kernel spewed forth more information than the iPXE.KRN. I now had a problem where I wanted to boot from the local CDROM and not from the SAN Device, but *after* it became registered. This is my http://192.168.1.2/win7/ipxe.ipxe script:
#!ipxe
# set skip-san-boot 1
set keep-san 1
If I uncomment skip-san-boot then it will boot from the local CD-ROM. You'll need to recomment it if you want it to boot from the SAN. Magically, the Windows 7 install DVD picked up the SAN device during the install, no hacked WinPE required.
And that's it. Booting from the UNDIONLY.KPXE works where iPXE.KRN does not.
And that will get you a iSCSI booting disk. I suspect I can change PXELinux to boot the UNDIONLY.KPXE. I prefer to use PXELinux because if I want to burn a bootable CD/DVD or USB stick I can just transfer my entire PXELinux folder structure over for SYSLinux or ISOLinux as a boot loader.
Next I'm going to try differencing disks. The goal for this little project is to see if I can setup a render farm by iSCSI booting computers and have them join automatically. This way if you need more power added to your farm you can just add any hardware, boot it up via PXE and it will launch into an environment where everything is pre-configured and ready to go.
This is my ipxe.ipxe that works with iPXE.KRN after been chainloaded by pxelinux.0:
#!ipxe
dhcp
sanhook ${root-path}
set net0/skip-san-boot 1
set net0/keep-san 1
prompt --key 0x02 --timeout 4000 Press Ctrl-B for the iPXE command line... && shell ||
exit
I set the skip-san-boot so I could boot from a regular Windows CD. You'll want to remove that line to actually boot from the SAN.
Keep in mind there is a gateway issue with MS's iSCSI implementation. It will add a static route to the SAN IP so you will either need to clear the gateway via the iPXE script or have the software target on the same location as your router (or have your router route local LAN traffic).
To get iSCSI working the first thing I did was install the Microsoft Software Target 3.3 on a server machine. It's pretty simple. Go to iSCSI Targets and create a new target. Whatever you name it will be on the IQN so I've kept it short. The iSCSI Initators Identifiers is like MAC Address filtering for a DHCP server, if you don't match you can't connect to the iSCSI target. So set the SII to whatever IP, MAC Address or IQN you plan on using. If you're like me and wasn't sure what the IQN will be set to, preferring to have iPXE's generated one; the Windows event viewer Application log will tell you what the IQN is when it fails to connect. Look for Event ID 22.
Highlighted is the IQN that tried to connect and failed. Add it to the SII and you'll be good to go the next time.
When you are done creating the target you need to create the Virtual Disk (VHD) for the target. Right-click on the target and go "Create Virtual Disk for iSCSI Target" and follow the prompts until you have your vDisk associated with the target.
We are now done on the server side. To test the connection I launched iSCSI initiator on the same server and tried to connect to the iSCSI Software Target. It had a "Target Error" as the error message. To get around this I enabled loopback.
HKLM\Software\Microsoft\iSCSI Target
Value Name: AllowLoopBack
Type: REG_DWORD
Value: 1 (Default is 0)
This will enable you to connect to your iSCSI target.
I could now connect to the iSCSI target that resided on the same server and validate the software target was working correctly.
Now to get the client side working. My goal with this is to PXE boot some client machines with differencing VHD's off a golden Windows 7 image. I encountered numerous issues attempting to do this and I'll share with you my problems and how I solved them.
The first thing I did was configure PXE booting off the Microsoft DHCP server. I was going to make it launch PXELinux prior to iPXE and may modify my DHCP to do so in the future, but below is a screenshot of my working settings:
I don't think 043 Vendor Specific Info is required. I put it in when I was trying to get PXELinux working. This is a working DHCP config.
# These default options can be changed in the geniso script
SAY iPXE ISO boot image
TIMEOUT 30
DEFAULT ipxe.lkrn
LABEL ipxe.lkrn
KERNEL ipxe.krn
INITRD ipxe.ipxe
Can you spot the error already?
dhcp
set keep-san 1
sanhook --drive 0x80 iscsi:192.168.1.2::::iqn.1991-05.com.microsoft:aclgdc01-t1-target
sanboot --nodescribe --drive 0xe0 http://192.168.1.2/win7/winpe.iso
My ipxe.ipxe script file. Everything I read said this should work.
PXELinux was booting the iPXE kernel, The iSCSI target wasn't detected natively by the Windows 7/2008 DVD's (which everything I read said that it should be). To correct this I made a modified WinPE with the iSCSI Initiator builtin. When I booted up that WinPE I could start the MSISCSI service and connect to the target. I thought things looked good and I could format the target and make folders/files on it. I could even bootsect it. I then mapped a network drive to the Windows installer files (which iPXE recommends) then ran setup.exe. I got to the part where I could choose the hard disk but Windows wouldn't let me install on it giving me an error message.
"Windows cannot be installed to Disk <#> Partition <#>. (Show details)" -> "Windows cannot be installed to this disk. iSCSI deployment is disabled since no NICs referenced in the iBFT can be resolved to actual NT-visible devices. Windows cannot be installed to this disk. This computer's hardware may not support booting to this disk.
Alright, at least I was making progress. From here I had to find out what a iBFT was and why can't Windows resolve it when I'm staring straight at the hard disk. The importance of it is found here.
"When the pre-boot loader starts, it loads a real-mode network stack driver. The loader contains an iSCSI initiator which logs on to the iSCSI target and mount the boot disk to the system. Another function of the loader is to populate the iSCSI Boot Firmware Table (iBFT), which is required for iSCSI boot. The Boot Parameter driver in Windows will load the parameters from the iBFT, and the Microsoft iSCSI Software Initiator will be able to connect to the iSCSI target using the parameters set in the iBFT. The importance of the iBFT is to be able to share the parameters between the iSCSI boot initiator (which establishes the session in the preboot phase) and the Microsoft iSCSI initiator (which establish the session after Windows boots)."
So my iPXE isn't storing it's values in the iBFT. This seemed weird to me because I could see it preserving the connection when I booted. Everything I read said the "set keep-san 1" is the magic to storing the iPXE values in the iBFT.
Isn't that what Registered SAN Device 0x80 means? That it's registered in the iBFT?
So it appeared to be working and I thought maybe it's Hyper-V. I read other people using Hyper-V were able to get this to work, but I'm stumped. It won't work for me. So I tried VMWare Player. I had the same issue there. No NICs referenced in the iBFT even though I could use the MS Initiator to connect to the target.
At this point I was getting pretty frustrated. For all intent and purposes this should work. So I went back to ipxe.org and read their Windows Deployment Service guide and setup WDS and made a WDS wim thinking maybe it had some magic touch; even though I had read that the standard install media should work.
Well, the WDS image didn't work either. At this point I went back to ipxe.org and followed their PXE Chainloading guide exactly. Well, mostly exactly. I didn't want to make a reservation so I applied the setting across the entire DHCP by entering everything in Server Options (see the first screenshot of this post).
Like magic, as soon as I changed the kernel from iPXE.KRN to undionly.kpxe it showed me something different on the Hyper-V console:
This *feels* more promising.
Like Magic the undionly.kpxe kernel spewed forth more information than the iPXE.KRN. I now had a problem where I wanted to boot from the local CDROM and not from the SAN Device, but *after* it became registered. This is my http://192.168.1.2/win7/ipxe.ipxe script:
#!ipxe
# set skip-san-boot 1
set keep-san 1
If I uncomment skip-san-boot then it will boot from the local CD-ROM. You'll need to recomment it if you want it to boot from the SAN. Magically, the Windows 7 install DVD picked up the SAN device during the install, no hacked WinPE required.
And that's it. Booting from the UNDIONLY.KPXE works where iPXE.KRN does not.
And that will get you a iSCSI booting disk. I suspect I can change PXELinux to boot the UNDIONLY.KPXE. I prefer to use PXELinux because if I want to burn a bootable CD/DVD or USB stick I can just transfer my entire PXELinux folder structure over for SYSLinux or ISOLinux as a boot loader.
Next I'm going to try differencing disks. The goal for this little project is to see if I can setup a render farm by iSCSI booting computers and have them join automatically. This way if you need more power added to your farm you can just add any hardware, boot it up via PXE and it will launch into an environment where everything is pre-configured and ready to go.
UPDATE
I've been able to get pxelinux to boot iPXE.KRN. The trick is the ipxe launch file needs the net0 to have the keep-san set. Setting it globally didn't appear to make it set in net0 (which, I assume, becomes stored in the iBFT)This is my ipxe.ipxe that works with iPXE.KRN after been chainloaded by pxelinux.0:
#!ipxe
dhcp
sanhook ${root-path}
set net0/skip-san-boot 1
set net0/keep-san 1
prompt --key 0x02 --timeout 4000 Press Ctrl-B for the iPXE command line... && shell ||
exit
I set the skip-san-boot so I could boot from a regular Windows CD. You'll want to remove that line to actually boot from the SAN.
Keep in mind there is a gateway issue with MS's iSCSI implementation. It will add a static route to the SAN IP so you will either need to clear the gateway via the iPXE script or have the software target on the same location as your router (or have your router route local LAN traffic).
Sunday, November 11, 2012
Loopback iSCSI targets (aka, Target Error on iSCSI Initiator)
Enable the following registry key:
http://blogs.technet.com/b/csstwplatform/archive/2012/02/09/windows-svr-2008-r2-iscsi-initiator-getting-quot-target-error-quot-message-when-attempting-to-connect-to-iscsi-target-on-localhost.aspx
http://blogs.technet.com/b/csstwplatform/archive/2012/02/09/windows-svr-2008-r2-iscsi-initiator-getting-quot-target-error-quot-message-when-attempting-to-connect-to-iscsi-target-on-localhost.aspx
HKLM\Software\Microsoft\iSCSI Target
Value Name: AllowLoopBack
Type: REG_DWORD
Value: 1 (Default is 0)
This will enable you to connect to your iSCSI target.
Tuesday, October 30, 2012
Debug AppV package by opening a command prompt
Open a command prompt and then run the following:
SFTMIME QUERY OBJ:APP /SHORT
IT999 2.3
TTEditor 7.1
Paris 3.7
SFTTRAY /EXE cmd.exe /LAUNCH "Paris 3.7"
This will launch the cmd.exe in the package.
Nice.
SFTMIME QUERY OBJ:APP /SHORT
IT999 2.3
TTEditor 7.1
Paris 3.7
SFTTRAY /EXE cmd.exe /LAUNCH "Paris 3.7"
This will launch the cmd.exe in the package.
Nice.
Wednesday, October 24, 2012
Creating a batch file that accepts parameters
We are App-V'ing a bunch of our applications and one of the applications requires a different .ini file depending if it's test, production or training. To get around creating 3 different packages with just a single file, I've written a pre-launch batch file that will auto-create the .ini depending on the parameters passed to it.
:===========================================================================================
: Paris Pre-launch script for App-V
: By Trentent Tye
: 2012-10-24
:
:
: This command file will take numerous parameters for launching the specific type
: of Paris application. It will autogenerate an INI file that Paris uses on
: launch to self configure. If no parameter is passed, it's assumed to be
: commented out in the INI file.
:
: This file should be launched like so:
: paris.cmd PARA request=0 hostname=nice servergroup=development_3861
:
: it will automatically find the variable without an equal sign and assume
: that it is the alias. Everything else gets matched up to the [Host]
: section of the .ini
:1) Pull string off the command line
:2) filter out " and '
:3) break each set out by spaces
:4) save to temp file
:5) iterate through temp file (for) and create variables.
@ECHO OFF
ECHO Launching Paris
SET PARAMS=%*
:NOTE: We are replacing quotations with whitespace characters! Ensure there is no
:whitespace in the parameters, but whitespace *between* parameters.
call set PARAMS=%%PARAMS:"= %%
call set PARAMS=%%PARAMS:'= %%
ECHO %PARAMS%
:Break each set of parameters into it's own set seperated by the equals sign.
:If there is no parameter stored we "breakout"
for /f "tokens=1-26 delims= " %%A IN ("%PARAMS%") DO (
IF '%%A' EQU '' GOTO BREAKOUT
ECHO %%A > "%TEMP%\variables.txt"
IF '%%B' EQU '' GOTO BREAKOUT
ECHO %%B >> "%TEMP%\variables.txt"
IF '%%C' EQU '' GOTO BREAKOUT
ECHO %%C >> "%TEMP%\variables.txt"
IF '%%D' EQU '' GOTO BREAKOUT
ECHO %%D >> "%TEMP%\variables.txt"
IF '%%E' EQU '' GOTO BREAKOUT
ECHO %%E >> "%TEMP%\variables.txt"
IF '%%F' EQU '' GOTO BREAKOUT
ECHO %%F >> "%TEMP%\variables.txt"
IF '%%G' EQU '' GOTO BREAKOUT
ECHO %%G >> "%TEMP%\variables.txt"
IF '%%H' EQU '' GOTO BREAKOUT
ECHO %%H >> "%TEMP%\variables.txt"
IF '%%I' EQU '' GOTO BREAKOUT
ECHO %%I >> "%TEMP%\variables.txt"
IF '%%J' EQU '' GOTO BREAKOUT
ECHO %%J >> "%TEMP%\variables.txt"
IF '%%K' EQU '' GOTO BREAKOUT
ECHO %%K >> "%TEMP%\variables.txt"
IF '%%L' EQU '' GOTO BREAKOUT
ECHO %%L >> "%TEMP%\variables.txt"
)
:BREAKOUT
:Now we iterate through the temp file and auto-create the Paris.ini
for /f "tokens=1-2 delims==" %%A IN ('TYPE "%TEMP%\variables.txt"') DO (
IF /I '%%A' EQU 'REQUEST' set REQUEST=%%B
IF /I '%%A' EQU 'OBJECTNAME' set OBJECTNAME=%%B
IF /I '%%A' EQU 'HOSTNAME' set HOSTNAME=%%B
IF /I '%%A' EQU 'REQUESTBROKER' set REQUESTBROKER=%%B
IF /I '%%A' EQU 'RequestBrokerBackup' set RequestBrokerBackup=%%B
IF /I '%%A' EQU 'ServerGroup' set ServerGroup=%%B
IF /I '%%B' EQU '' set ALIAS=%%A
)
:Now that we have all the parameters for the ini file we can create it.
SET PARISPATH="%TEMP%\paris.ini"
ECHO [PreLogin] >"%PARISPATH%"
ECHO ClientDLL=STAPPClientLogin >>"%PARISPATH%"
ECHO FunctionName=DoLogin >>"%PARISPATH%"
ECHO ServerDLL=STServerLogin >>"%PARISPATH%"
ECHO DataModule=Login >>"%PARISPATH%"
ECHO. >>"%PARISPATH%"
ECHO [PostLogin] >>"%PARISPATH%"
ECHO ServerDLL=STSRVLogin >>"%PARISPATH%"
ECHO DataModule=Login >>"%PARISPATH%"
ECHO. >>"%PARISPATH%"
ECHO [Timer] >>"%PARISPATH%"
ECHO Enabled=0 >>"%PARISPATH%"
ECHO Interval=10000 >>"%PARISPATH%"
ECHO. >>"%PARISPATH%"
ECHO [Host] >>"%PARISPATH%"
if /I "%REQUEST%" EQU "" ECHO #Request=0 >>"%PARISPATH%"
if /I "%REQUEST%" NEQ "" ECHO Request=%REQUEST% >>"%PARISPATH%"
if /I "%OBJECTNAME%" EQU "" ECHO #objectname=I4AppServer >>"%PARISPATH%"
if /I "%OBJECTNAME%" NEQ "" ECHO objectname=%OBJECTNAME% >>"%PARISPATH%"
if /I "%HOSTNAME%" EQU "" ECHO #hostname=AComputerName >>"%PARISPATH%"
if /I "%HOSTNAME%" NEQ "" ECHO hostname=%HOSTNAME% >>"%PARISPATH%"
if /I "%REQUESTBROKER%" EQU "" ECHO #RequestBroker=AComputerName >>"%PARISPATH%"
if /I "%REQUESTBROKER%" NEQ "" ECHO RequestBroker=%REQUESTBROKER% >>"%PARISPATH%"
if /I "%RequestBrokerBackup%" EQU "" ECHO #RequestBrokerBackup=AnotherComputerName >>"%PARISPATH%"
if /I "%RequestBrokerBackup%" NEQ "" ECHO RequestBrokerBackup=%RequestBrokerBackup% >>"%PARISPATH%"
if /I "%ServerGroup%" EQU "" ECHO #ServerGroup=AnotherComputerName >>"%PARISPATH%"
if /I "%ServerGroup%" NEQ "" ECHO ServerGroup=%ServerGroup% >>"%PARISPATH%"
ECHO. >>"%PARISPATH%"
ECHO [Settings] >>"%PARISPATH%"
ECHO MaxLookup=200 >>"%PARISPATH%"
ECHO NotifyInterval=30000 >>"%PARISPATH%"
ECHO #Interval between refresh of InBox screen (1second=1000) >>"%PARISPATH%"
ECHO Helpfile=paris1.chm >>"%PARISPATH%"
:ADD COPY COMMAND
:ADD LAUNCH COMMAND
:copy /y "%PARISPATH%" "B:\In4tek_Paris_37_MNT\Paris\bin\STAPPParisShellDCOM.INI"
ECHO "B:\In4tek_Paris_37_MNT\Paris\bin\STAPPParisShellDCOM.exe -alias %ALIAS%
type "%PARISPATH%"
Thursday, September 13, 2012
ESXi 5.1 on MacBook 4,1
Well... I got ESXi 5.0 installed on the MacBook but I was unable to get Mountain Lion to work. VMWare just came out with ESXi 5.1 which supports Mountain Lion so I attempted to install ESXi 5.1 on a USB key and get it up and running on my MacBook. 5.1 was a little different from 5.0 as the installerhelper.sh appears to operate differently...? Anyways, what I had to do was slipstream the sky2 driver into the ESXi 5.1 image, boot into "ESXi 'No Network Adapters Found'" then Fn-Option-F1 into the console. I then typed the following commands:
vmkload_mod sky2
esxcfg-init -n
vmkload_mod lvmdriver
install
Without the lvmdriver the install would not see the storage (USB or HDD)
I am now installing ESXi 5.1 onto my MacBook. Hopefully, I'll be able to run Mountain Lion from it :)
vmkload_mod sky2
esxcfg-init -n
vmkload_mod lvmdriver
install
Without the lvmdriver the install would not see the storage (USB or HDD)
I am now installing ESXi 5.1 onto my MacBook. Hopefully, I'll be able to run Mountain Lion from it :)
Tuesday, September 04, 2012
ESXi 5 on older MacBook 4,1
I'm looking to get my MacBook 4,1 under a little more utilization and I thought playing with VMWare's ESXi-5 on it would be interesting. As well, I'm hoping that I'll be able to install a virtualized Mountain Lion in there (unsupported natively on this MacBook). My first attempt at installing ESXi 5U1 was a miserable disaster. ESXi won't let you complete the installation process without a NIC. This triggered a search to find what NIC was in my MacBook (Marvell Yukon 88E8055 VEN_11AB&DEV_436A) and a requirement to get it working.
I found this thread:
http://www.vm-help.com/forum/viewtopic.php?f=25&t=3558&start=10
It got me started on the path I needed to enable the drivers for my MacBook. I found that the Marvell driver is already included but it is only enabled for two device ID's and neither were the same as my macbook's; but they were from the same family.
http://www.vm-help.com/esx41/sky2_driver.php
I later found that the driver supports my device ID but you need to edit a text file in the VMWare driver files to enable it. This will not work though, because VMWare signs their files and if there is a mismatch it will error out (unable to boot or corrupt image or some such). To get around this we need to inject the driver into the ESXi installer.
In order to do this I needed to understand how to make a driver injectable. It appears whatever you make will overwrite files during the unpacking process when ESXi is booting. I was able to "sort-of" confirm this by packing up the sky2 driver and including my Device ID in the ESXi driver ID file. When I packed up the sky2 binary driver in addition to the text files the install would error out. Since it's redundant to include the driver as well, I just tried including the driver text file that enables the deviceID. This file could be located here:
"\etc\vmware\driver.map.d\sky2.map"
To also make this more complicated I did everything on Windows and had to install UnxUtils and UnxUpdates and some Cygwin tools to do the archiving/unarchiving.
By editing sky2.map I could add my device ID:
regtype=linux,bus=pci,id=11ab:4354 0000:0000,driver=sky2,class=network
regtype=linux,bus=pci,id=11ab:4362 0000:0000,driver=sky2,class=network
regtype=linux,bus=pci,id=11ab:436A 0000:0000,driver=sky2,class=network
I compressed the file into a .tgz (bsdtar -cvzf sky2.tgz "etc") and then used ESXi Customizer 2.7 to inject it into a generic ESXi 5.0U1 image. I then used Linux Live USB Creator to move the ISO to a USB key that was made bootable.
I could now boot my MacBook4,1 off the USB key. At least, it worked to a point. I got to a stage where I was notified that I had no Network Adapters Found. At this point I dropped into the ESXi console (Fn-Option-F1), logged in to root and ran the following commands:
vmkload_mod sky2
#loads the sky2 driver
lspci -p
#confirms sky2 driver is loaded for 436A DEV ID
esxcfg-init -n
#initializes network for default settings
installerhelper.sh
#preps install command
install
The install command kicked me out to the default console where I was sitting at the "Network Adapters Not Found" screen. Simply Fn-Option-F1 to return to the console and run through the install prompts. Choose the same USB key you used earlier (or choose a new one if you prefer) and do the install. Once it's complete; restart onto the USB key. You should go into a full ESXi install but the network (for me anyways) was still no working correctly. I had to enable the console through the "GUI" of the text screen, drop into the console and run vmkload_mod sky2 and I had network again and was up and running. Once I can figure out how to automatically run that command I will come back and update this post. But for now I have ESXi working on a old MacBook and hopefully I'll be able to install Mountain Lion on this old workstation :)
I found this thread:
http://www.vm-help.com/forum/viewtopic.php?f=25&t=3558&start=10
It got me started on the path I needed to enable the drivers for my MacBook. I found that the Marvell driver is already included but it is only enabled for two device ID's and neither were the same as my macbook's; but they were from the same family.
http://www.vm-help.com/esx41/sky2_driver.php
I later found that the driver supports my device ID but you need to edit a text file in the VMWare driver files to enable it. This will not work though, because VMWare signs their files and if there is a mismatch it will error out (unable to boot or corrupt image or some such). To get around this we need to inject the driver into the ESXi installer.
In order to do this I needed to understand how to make a driver injectable. It appears whatever you make will overwrite files during the unpacking process when ESXi is booting. I was able to "sort-of" confirm this by packing up the sky2 driver and including my Device ID in the ESXi driver ID file. When I packed up the sky2 binary driver in addition to the text files the install would error out. Since it's redundant to include the driver as well, I just tried including the driver text file that enables the deviceID. This file could be located here:
"\etc\vmware\driver.map.d\sky2.map"
To also make this more complicated I did everything on Windows and had to install UnxUtils and UnxUpdates and some Cygwin tools to do the archiving/unarchiving.
By editing sky2.map I could add my device ID:
regtype=linux,bus=pci,id=11ab:4354 0000:0000,driver=sky2,class=network
regtype=linux,bus=pci,id=11ab:4362 0000:0000,driver=sky2,class=network
regtype=linux,bus=pci,id=11ab:436A 0000:0000,driver=sky2,class=network
I compressed the file into a .tgz (bsdtar -cvzf sky2.tgz "etc") and then used ESXi Customizer 2.7 to inject it into a generic ESXi 5.0U1 image. I then used Linux Live USB Creator to move the ISO to a USB key that was made bootable.
I could now boot my MacBook4,1 off the USB key. At least, it worked to a point. I got to a stage where I was notified that I had no Network Adapters Found. At this point I dropped into the ESXi console (Fn-Option-F1), logged in to root and ran the following commands:
vmkload_mod sky2
#loads the sky2 driver
lspci -p
#confirms sky2 driver is loaded for 436A DEV ID
esxcfg-init -n
#initializes network for default settings
installerhelper.sh
#preps install command
install
The install command kicked me out to the default console where I was sitting at the "Network Adapters Not Found" screen. Simply Fn-Option-F1 to return to the console and run through the install prompts. Choose the same USB key you used earlier (or choose a new one if you prefer) and do the install. Once it's complete; restart onto the USB key. You should go into a full ESXi install but the network (for me anyways) was still no working correctly. I had to enable the console through the "GUI" of the text screen, drop into the console and run vmkload_mod sky2 and I had network again and was up and running. Once I can figure out how to automatically run that command I will come back and update this post. But for now I have ESXi working on a old MacBook and hopefully I'll be able to install Mountain Lion on this old workstation :)
Monday, July 09, 2012
Enable RemoteApp on Server 2008/Windows 7
We have two Citrix farms, a XenApp 5 farm and a XenApp 6 farm. XenApp 6 only supports 64bit OS's.
Step 1
Run regedit (registry editor) and locate the key TsAppAllowList
a) New Key, Applications.
b) Under Applications, create New Key, 1234567 (the key name is not important, we just need any key for next two steps)
c) In the new key, Create New -> String Value, Name. Set value to Notepad
d) Also in the new key, Create New -> String Value, Path. Set to c:\windows\system32\Notepad.exe
b) Under Applications, create New Key, 1234567 (the key name is not important, we just need any key for next two steps)
c) In the new key, Create New -> String Value, Name. Set value to Notepad
d) Also in the new key, Create New -> String Value, Path. Set to c:\windows\system32\Notepad.exe
a) Edit fDisableAllowList value, and set to 1
Step 2 – Creating the RDP file to access the RemoteApp
Now the guest operating system has a RemoteApp created we need to use a Remote Desktop Connection to access that application.
1. Run remote desktop connection, setup your desired settings as you would in a normal connection
2. Save the settings to an RDP file.
3) Use Notepad to open the RDP file to edit the configuration file,
a) Modify the setting; remoteapplicationmode:i:0 to remoteapplicationmode:i:1
b) Add the setting; remoteapplicationprogram:s:Notepad
c) Add the setting; disableremoteappcapscheck:i:1
d) Add the setting; alternate shell:s:rdpinit.exe
e) Save the RDP file
Final thought
Similar to VirtualBox seamless mode, you will not be able to move the floating guest application window between monitors, unless you save the RDP to use all monitors available. Either set this option prior to saving the RDP file, or edit the RDP setting multimon:i:1.
Thursday, June 07, 2012
Retrieving Citrix user accounts via PowerShell
Here's a neat little two liner to pull all the AD accounts associated with Citrix applications:
$accounts = Get-XAApplicationReport * | select-object Accounts
$accounts | foreach {$_.accounts | select-object AccountDisplayName} | export-csv "%userprofile%\desktop\app.csv" -noclobber
Awesome.
Here's a neat little two liner to pull all the AD accounts associated with Citrix applications:
$accounts = Get-XAApplicationReport * | select-object Accounts
$accounts | foreach {$_.accounts | select-object AccountDisplayName} | export-csv "%userprofile%\desktop\app.csv" -noclobber
Awesome.
Wednesday, May 16, 2012
Query remote registry for My Documents location
A common question I get is, "Can we move all these users My Documents folder from Server A to Server B"?
"Sure," I'll respond, "we'll just update their AD home directory attribute and have them log off and log back on."
Inevitably, this will fail in some capacity. The users don't wait for the copy to complete is an example and then it fails and the My Documents is still pointing to their old server. To correct this issue you can pre-copy the files then when doing the login copy, folder redirection will only copy changed files. This can still take a while but it's much faster then copying everything, especially with a big directory.
Eventually, I'll get asked, "we want to shut down the old server, can we verify that all the users my docs have been copied off and their computers are pointing to the correct location?"
In order to accomplish this effectively, I wrote a script that runs through a list of computers you give it and it checks the registry and presents you a list of all the network "My Documents" it finds. This is the script:
:Find-redir.cmd
:This next bit will query the registry to see if they are redirecting already...
del /q "%temp%\redir.txt"
:you need to drop a list of computers on this file.
FOR /F "tokens=*" %%a IN ('type %1') DO (
echo =============================================== >> "%temp%\redir.txt"
echo %%a >> "%temp%\redir.txt"
reg query \\%%a\HKU | findstr /V /C:"_Classes" | findstr /R /V /C:"S-1-5-1[89]" | findstr /R /V /C:"S-1-5-20" | findstr /v /c:".DEFAULT" | findstr /v /c:"!" | findstr /c:"HKEY_USERS\S" > "%temp%\reg-user.txt"
for /f "tokens=*" %%A IN ('type "%temp%\reg-user.txt"') DO reg query "\\%%a\%%A\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" | findstr \\\\ >> "%temp%\redir.txt"
echo =============================================== >> "%temp%\redir.txt"
)
notepad "%temp%\redir.txt"
To use the script; get a list of computers or IP addresses and then run the script as:
find-redir.cmd "list-of-computers.txt"
The list of computers.txt can look like:
192.168.1.1
192.168.1.2
Laptop1
Laptop2
"Sure," I'll respond, "we'll just update their AD home directory attribute and have them log off and log back on."
Inevitably, this will fail in some capacity. The users don't wait for the copy to complete is an example and then it fails and the My Documents is still pointing to their old server. To correct this issue you can pre-copy the files then when doing the login copy, folder redirection will only copy changed files. This can still take a while but it's much faster then copying everything, especially with a big directory.
Eventually, I'll get asked, "we want to shut down the old server, can we verify that all the users my docs have been copied off and their computers are pointing to the correct location?"
In order to accomplish this effectively, I wrote a script that runs through a list of computers you give it and it checks the registry and presents you a list of all the network "My Documents" it finds. This is the script:
:Find-redir.cmd
:This next bit will query the registry to see if they are redirecting already...
del /q "%temp%\redir.txt"
:you need to drop a list of computers on this file.
FOR /F "tokens=*" %%a IN ('type %1') DO (
echo =============================================== >> "%temp%\redir.txt"
echo %%a >> "%temp%\redir.txt"
reg query \\%%a\HKU | findstr /V /C:"_Classes" | findstr /R /V /C:"S-1-5-1[89]" | findstr /R /V /C:"S-1-5-20" | findstr /v /c:".DEFAULT" | findstr /v /c:"!" | findstr /c:"HKEY_USERS\S" > "%temp%\reg-user.txt"
for /f "tokens=*" %%A IN ('type "%temp%\reg-user.txt"') DO reg query "\\%%a\%%A\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" | findstr \\\\ >> "%temp%\redir.txt"
echo =============================================== >> "%temp%\redir.txt"
)
notepad "%temp%\redir.txt"
To use the script; get a list of computers or IP addresses and then run the script as:
find-redir.cmd "list-of-computers.txt"
The list of computers.txt can look like:
192.168.1.1
192.168.1.2
Laptop1
Laptop2
Monday, May 14, 2012
I've had a bit of a battle getting PowerShell to work on creating remote shares with the permissions I want. I think I have it working now in a fairly minimalist fashion.
Enjoy!
#create a share using WMI and
PowerShell
#
#5/14/2012
- By Trentent Tye
#
#To
create a share with PowerShell utilizing WMI (so you don't need
#to
use PSRemoting) you need to do the following:
#1)
Create the Win32_Share class
#2)
Create the Security Descriptor for the share
#3)
Create the ACE for the share
#4)
Create the Trustee fo rthe ACE
#5)
Set all the variables
#6)
Create the share.
#
#The
next lines sets a computer (%cn%) to "EVERYONE FULL CONTROL" on the
#share
"HomeDirs"
$cshare = [WMIClass]"\\%cn%\root\cimv2:Win32_Share"
$securityDescriptor = ([WMIClass] "\\%cn%\root\cimv2:Win32_SecurityDescriptor").CreateInstance()
$ACE = ([WMIClass] "\\%cn%\root\cimv2:Win32_ACE").CreateInstance()
$Trustee = ([WMIClass] "\\%cn%\root\cimv2:Win32_Trustee").CreateInstance()
$Trustee.Name = "EVERYONE"
$Trustee.Domain = $Null
$Trustee.SID = @(1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0)
$ace.AccessMask = 2032127
$ace.AceFlags = 3
$ace.AceType = 0
$ACE.Trustee = $Trustee
$securityDescriptor.DACL += $ACE.psObject.baseobject
#trying
to create share... variables are:
#,,,(if $Null set to maximum
allowed),,,
$result = $cshare.create("%homeDrive%:\homedirs","homedirs",0,$Null,"Home
Directory Share",$Null,$securityDescriptor)
}
Enjoy!
Tuesday, April 10, 2012
Domain Controller doesn't replicate DNS and has other replication issues
We recently demoted a global catalog domain controller and then re-promoted because of issues we were having post-demotion. When a DC is demoted it changes it's computer account to have less rights then it would if it were a DC. Somewhere along the line the promotion didn't change it's account back and after the computer account password expired we started having replications issues. This didn't really affect us too much until 14 days after the password expired and the DC couldn't replicate back to the domain. All of our DNS zones couldn't replicate to it and subsequently became "stale" and were scavenged and removed. This caused issues for everyone at that site as they couldn't access various resources that we utilize DNS for.
The symptoms were:
All DNS zones were gone except for the primary zone.
"error no trust sam account" occurred while running "nltest /dsregdns"
This error was in the DNS event log:
repadmin /showreps reported it failed.
The solution was from here:
http://support.microsoft.com/default.aspx?scid=kb;en-us;329860
The symptoms were:
All DNS zones were gone except for the primary zone.
"error no trust sam account" occurred while running "nltest /dsregdns"
This error was in the DNS event log:
"The DNS server detected that it is not enlisted in the replication scope of the directory partition ForestDnsZones.ccs.corp. This prevents the zones that should be replicated to all DNS servers in the ccs.corp forest from replicating to this DNS server.And this error:
To create or repair the forest-wide DNS directory partition, open the the DNS console. Right-click the applicable DNS server, and then click 'Create Default Application Directory Partitions'. Follow the instructions to create the default DNS application directory partitions. For more information, see 'To create the default DNS application directory partitions' in Help and Support. "
The attempt to establish a replication link for the following writable directory partition failed.dcdiag reported the last replication was 2 weeks ago
repadmin /showreps reported it failed.
The solution was from here:
http://support.microsoft.com/default.aspx?scid=kb;en-us;329860
WARNING: If you use the ADSI Edit snap-in, the LDP utility, or any other LDAP version 3 client, and you incorrectly modify the attributes of Active Directory objects, you can cause serious problems. These problems may require you to reinstall Microsoft Windows 2000 Server, Microsoft Exchange 2000 Server, or both. Microsoft cannot guarantee that problems that occur if you incorrectly modify Active Directory object attributes can be solved. Modify these attributes at your own risk.
On a domain controller that is in the "healthy" part of the domain (not the domain controller with which you experience the issue), install the Windows 2000 Support Tools if they have not already been installed. For additional information about how to install the Windows 2000 Support Tools, click the article number below to view the article in the Microsoft Knowledge Base:
301423 How to Install the Windows 2000 Support Tools to a Windows 2000 Server-Based Computer
Start the ADSI Edit snap-in. To do so, click Start, point to Programs, point to Windows 2000 Support Tools, point to Tools, and then click ADSI Edit.
Expand Domain NC [server.example.com] (where server is the name of the domain controller and example.com is the name of the domain.
Expand DC=example,DC=com.
Expand OU=Domain Controllers, right-click CN=ServerName (where ServerName is the domain controller with which you experience the issues that are described in the "Symptoms" section of this article), and then click Properties.
Click the Attributes tab (if it is not already selected).
In the Select which properties to view list, click Both, and then click userAccountControl in the Select a property to view list.
If the Value(s) box does not contain 532480, type 532480 in the Edit Attribute box, and then click Set.
Click Apply, click OK, and then quit the ADSI Edit snap-in
Thursday, March 29, 2012
List of exportable AD attributes
It appears the following AD attributes are exportable from LDIFDE or CSVDE:
DN,objectClass,ou,distinguishedName,name,description,sAMAccountName,objectCategory,instanceType,whenCreated,whenChanged,uSNCreated,uSNChanged,dSCorePropagationData,cn,member,groupType,displayName,info,extensionAttribute1,managedBy,publicDelegatesBL,extensionAttribute14,extensionAttribute15,mail,sn,givenName,homeMTA,proxyAddresses,homeMDB,garbageCollPeriod,mDBUseDefaults,mailNickname,protocolSettings,internetEncoding,userAccountControl,badPwdCount,codePage,countryCode,badPasswordTime,lastLogoff,lastLogon,pwdLastSet,primaryGroupID,accountExpires,logonCount,showInAddressBook,legacyExchangeDN,userPrincipalName,textEncodedORAddress,msExchHomeServerName,msExchMailboxSecurityDescriptor,msExchUserAccountControl,msExchMailboxGuid,msExchPoliciesIncluded,msExchMailboxAuditLogAgeLimit,msExchRecipientDisplayType,msExchAddressBookFlags,msExchRBACPolicyLink,msExchDumpsterQuota,msExchArchiveQuota,msExchRecipientTypeDetails,msExchMDBRulesQuota,msExchTransportRecipientSettingsFlags,msExchArchiveWarnQuota,msExchDumpsterWarningQuota,msExchUMEnabledFlags2,msExchModerationFlags,msExchProvisioningFlags,msExchUMDtmfMap,msExchBypassAudit,msExchMailboxAuditEnable,msExchWhenMailboxCreated,msExchTextMessagingState,reportToOriginator,msExchRequireAuthToSendTo,msExchALObjectVersion,msExchArbitrationMailbox,msExchCoManagedByLink,msExchHideFromAddressLists,msExchGroupDepartRestriction,msExchGroupJoinRestriction,reportToOwner,replicatedObjectVersion,replicationSignature,msExchADCGlobalNames,dLMemDefault,oOFReplyToOriginator,msExchPoliciesExcluded,delivContLength,authOrig,dLMemSubmitPerms,dLMemSubmitPermsBL,displayNamePrintable,altRecipientBL,adminCount,hideDLMembership,managedObjects
I've exported using CSVDE using all these attributes and managed to import back into a different AD domain (and finding and replacing DC=XXX,DC=COM) and these attributes appear to import cleanly without error
DN,objectClass,ou,distinguishedName,name,description,sAMAccountName,objectCategory,instanceType,whenCreated,whenChanged,uSNCreated,uSNChanged,dSCorePropagationData,cn,member,groupType,displayName,info,extensionAttribute1,managedBy,publicDelegatesBL,extensionAttribute14,extensionAttribute15,mail,sn,givenName,homeMTA,proxyAddresses,homeMDB,garbageCollPeriod,mDBUseDefaults,mailNickname,protocolSettings,internetEncoding,userAccountControl,badPwdCount,codePage,countryCode,badPasswordTime,lastLogoff,lastLogon,pwdLastSet,primaryGroupID,accountExpires,logonCount,showInAddressBook,legacyExchangeDN,userPrincipalName,textEncodedORAddress,msExchHomeServerName,msExchMailboxSecurityDescriptor,msExchUserAccountControl,msExchMailboxGuid,msExchPoliciesIncluded,msExchMailboxAuditLogAgeLimit,msExchRecipientDisplayType,msExchAddressBookFlags,msExchRBACPolicyLink,msExchDumpsterQuota,msExchArchiveQuota,msExchRecipientTypeDetails,msExchMDBRulesQuota,msExchTransportRecipientSettingsFlags,msExchArchiveWarnQuota,msExchDumpsterWarningQuota,msExchUMEnabledFlags2,msExchModerationFlags,msExchProvisioningFlags,msExchUMDtmfMap,msExchBypassAudit,msExchMailboxAuditEnable,msExchWhenMailboxCreated,msExchTextMessagingState,reportToOriginator,msExchRequireAuthToSendTo,msExchALObjectVersion,msExchArbitrationMailbox,msExchCoManagedByLink,msExchHideFromAddressLists,msExchGroupDepartRestriction,msExchGroupJoinRestriction,reportToOwner,replicatedObjectVersion,replicationSignature,msExchADCGlobalNames,dLMemDefault,oOFReplyToOriginator,msExchPoliciesExcluded,delivContLength,authOrig,dLMemSubmitPerms,dLMemSubmitPermsBL,displayNamePrintable,altRecipientBL,adminCount,hideDLMembership,managedObjects
I've exported using CSVDE using all these attributes and managed to import back into a different AD domain (and finding and replacing DC=XXX,DC=COM) and these attributes appear to import cleanly without error
Tuesday, March 13, 2012
AppV and Application Compatibility
I was having an issue with a old application that we want to run on our Citrix XenApp 6 farm; Microsoft Enterprise Reporting 7.5 SP4 (7.5.303). Namely, it wouldn't run. It's not compatible with Server 2008 R2 unless you're running SP5. Well, we're going to get rid of it in a few months but we want to get rid of our 4.5 farm. So, we need to migrate the application to XenApp 6 and Server 2008R2 from Presentation Server 4.5 and Server 2003 SP1.
First thing I did was setup a Server 2003 SP1 box and installed the AppV sequencer on it and sequenced the application. I then set it to run on 2008R2 64bit and moved the package over to it. It would crash. Analysing the crash logs would present to me the error... ERAPP32 was crashing its heap. In order to get it to work I had to set it to run in compatibility mode for XPSP3. Once I set this it worked flawlessly. So what I needed to do was push this fix to the rest of our Citrix servers before deploying the AppV application. If you've ever read ACT (application compatibilty toolkit) and merging it with AppV it's kind of a difficult job.
But there is a easier way.
Stored in the registry is the AppCompatFlags key that contains the applications and the shims you can apply to an application. If you put the path to your AppV application it will actually enable it to run in the compatibility mode that you specify. This was my registry entry:
And now the application works almost wonderfully (ER is a painful application)
:)
First thing I did was setup a Server 2003 SP1 box and installed the AppV sequencer on it and sequenced the application. I then set it to run on 2008R2 64bit and moved the package over to it. It would crash. Analysing the crash logs would present to me the error... ERAPP32 was crashing its heap. In order to get it to work I had to set it to run in compatibility mode for XPSP3. Once I set this it worked flawlessly. So what I needed to do was push this fix to the rest of our Citrix servers before deploying the AppV application. If you've ever read ACT (application compatibilty toolkit) and merging it with AppV it's kind of a difficult job.
But there is a easier way.
Stored in the registry is the AppCompatFlags key that contains the applications and the shims you can apply to an application. If you put the path to your AppV application it will actually enable it to run in the compatibility mode that you specify. This was my registry entry:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
"Q:\\Enterprise Reporting\\ErApp\\erapp32.exe"="WINXPSP3 256COLOR DISABLETHEMES DISABLEDWM HIGHDPIAWARE RUNASADMIN"
And now the application works almost wonderfully (ER is a painful application)
:)
Monday, March 05, 2012
Utilizing PowerShell to make Citrix VM Templates
Because my company doesn't utilize provisioining servers for deploy new Citrix XenApp servers, I've had to come up with a couple of PowerShell scripts to make VMWare Templates that I can then deploy multiple XenApp servers. You need VMWare PowerCLI to run this script. This is my script:
This script does the following:
1) Sets the inputs from a piped in object (get-vm VMTOTEMPLATE | create-template)
2) Sets a series of variables ($vm, $name, $newname, $date, $templatename, etc.)
3) We setup a startup script on the target server to make into a template that:
a) Removes the computer from the domain
b) renames the computer to a generic name (XATEMPLATE)
c) Adds registry keys that will allow sysprep to run
d) Configures XenApp to "Image" mode
e) Shuts itself down once running the script is complete
f) deletes the script from running on startup
4) We then set the target to autologin with the local admin user name and password so the startup script in step 3 will be run
5) Begins the cloning by making a new-vm with the target machine
6) We unplug the NIC from VMWare so that when it starts up the script won't actually remove the machine from the domain, but will remove itself from the domain
7) start the clone
8) the PowerCLI will now wait till the machine turns itself off...
9) Then it will reconnect the NIC, remove any stale templates and then makes a new template and then removes the clone VM.
Done! :)
function create-template{
Param(
[CmdletBinding()]
[Parameter(ValueFromPipeline=$true,
Position=0,
Mandatory=$true,
HelpMessage="Insert Message")]
[ValidateNotNullOrEmpty()]
$InputObject,
[Parameter(Position=1,
Mandatory=$false,
HelpMessage="Insert Preferred Folder")]
$folder,
[Parameter(Position=2,
Mandatory=$false,
HelpMessage="Insert Preferred Target Datastore")]
$datastore,
[Parameter(Position=3,
Mandatory=$false,
HelpMessage="Insert Preferred Target Host")]
$vmhost,
[Parameter(Position=4,
Mandatory=$false,
HelpMessage="Insert Preferred Disk Storage Format")]
[ValidateSet("Thick","Thin")]
$format = "Thin"
)
PROCESS{
$InputObject | %{
$vm = Get-VM $_
$name = $vm.name
$newname = -join("clone-",$name)
$date = get-date -uformat "-%Y-%m-%d"
$templatename = -join("template-",$name,$date)
If ($datastore -eq $null){
$datastore = Get-Datastore -VM $vm
}
If ($folder -eq $null){
$folder = $vm.Folder
}
If ($vmhost -eq $null){
$vmhost = Get-Cluster -VM $vm | Get-VMHost | Get-Random | Where{$_ -ne $null}
}
Write-Host "VM = $vm"
Write-Host "Name = $name"
Write-Host "NewName = $newname"
Write-Host "DataStore = $datastore"
Write-Host "Folder = $folder"
Write-Host "VMHost = $vmhost"
write-Host "templatename=$templatename"
sleep 4
Write-Host "Setting up domain unjoin script..."
Remove-Item "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "netdom remove $name /Force"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "netdom renamecomputer $name /newname:XA6TEMPLATE /Force"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "REG ADD `"HKEY_LOCAL_MACHINE\SYSTEM\Setup\Status\SysprepStatus`" /v `"GeneralizationState`" /t
REG_DWORD /d 0x7 /f"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "REG ADD `"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
\SoftwareProtectionPlatform`" /v `"SkipRearm`" /t REG_DWORD /d 0x1 /f"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "`"C:\Program Files (x86)\Citrix\XenApp\ServerConfig\XenAppConfigConsole.exe`"
/ExecutionMode:ImagePrep /PrepMsmq:True"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "shutdown -s -t 90 -f"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "del /q `"c:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd"
Write-Host "Setting Autologon..."
psexec \\$name "REG.EXE" ADD `"\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`" /v `"DefaultUserName`" /d Administrator /f`"
sleep 5
psexec \\$name "REG.EXE" ADD `"\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`" /v `"DefaultPassword`" /d Hello /f`"
sleep 5
psexec \\$name "REG.EXE" ADD `"\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`" /v `"AutoAdminLogon`" /t REG_DWORD /d 0x1 /F`"
sleep 5
psexec \\$name "REG.EXE" ADD `"\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`" /v `"AutoLogonCount`" /t REG_DWORD /d 0x1 /F`"
Write-Host "Cloning"
New-VM -Name $newname -VM $vm -Location $folder -Datastore $datastore -VMHost $vmhost -DiskStorageFormat $format
Write-Host "Unplugging NIC..."
get-VM $newname | get-networkadapter | set-networkadapter -startconnected:$false -confirm:$false
Write-Host "Starting VM..."
start-vm $newname
Write-Host "Powering on clone..."
Remove-Item "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd"
Write-Host "We need to wait until the clone is powered off before we can template it..."
do {
sleep 1.0
Write "Waiting for shutdown of VMs"
} until (Get-VM $newname | Where { $_.PowerState -eq "poweredOff" })
write-host "System is powered on"
Write-Host "Creating NIC..."
get-VM $newname | get-networkadapter | set-networkadapter -startconnected:$true -confirm:$false
Write-Host "Removing any stale template-VM's"
remove-template $templatename -confirm:$false
Write-Host "Creating Template VM from clone"
new-template -VM $newname -name $templatename -Location $folder
Write-Host "Removing Clone VM"
remove-vm $newname -DeletePermanently -confirm:$false
}
}
}
This script does the following:
1) Sets the inputs from a piped in object (get-vm VMTOTEMPLATE | create-template)
2) Sets a series of variables ($vm, $name, $newname, $date, $templatename, etc.)
3) We setup a startup script on the target server to make into a template that:
a) Removes the computer from the domain
b) renames the computer to a generic name (XATEMPLATE)
c) Adds registry keys that will allow sysprep to run
d) Configures XenApp to "Image" mode
e) Shuts itself down once running the script is complete
f) deletes the script from running on startup
4) We then set the target to autologin with the local admin user name and password so the startup script in step 3 will be run
5) Begins the cloning by making a new-vm with the target machine
6) We unplug the NIC from VMWare so that when it starts up the script won't actually remove the machine from the domain, but will remove itself from the domain
7) start the clone
8) the PowerCLI will now wait till the machine turns itself off...
9) Then it will reconnect the NIC, remove any stale templates and then makes a new template and then removes the clone VM.
Done! :)
Utilizing PowerShell to make Citrix VM Templates
Because my company doesn't utilize provisioining servers for deploy new Citrix XenApp servers, I've had to come up with a couple of PowerShell scripts to make VMWare Templates that I can then deploy multiple XenApp servers. You need VMWare PowerCLI to run this script. This is my script:
This script does the following:
1) Sets the inputs from a piped in object (get-vm VMTOTEMPLATE | create-template)
2) Sets a series of variables ($vm, $name, $newname, $date, $templatename, etc.)
3) We setup a startup script on the target server to make into a template that:
a) Removes the computer from the domain
b) renames the computer to a generic name (XATEMPLATE)
c) Adds registry keys that will allow sysprep to run
d) Configures XenApp to "Image" mode
e) Shuts itself down once running the script is complete
f) deletes the script from running on startup
4) We then set the target to autologin with the local admin user name and password so the startup script in step 3 will be run
5) Begins the cloning by making a new-vm with the target machine
6) We unplug the NIC from VMWare so that when it starts up the script won't actually remove the machine from the domain, but will remove itself from the domain
7) start the clone
8) the PowerCLI will now wait till the machine turns itself off...
9) Then it will reconnect the NIC, remove any stale templates and then makes a new template and then removes the clone VM.
Done! :)
function create-template{
Param(
[CmdletBinding()]
[Parameter(ValueFromPipeline=$true,
Position=0,
Mandatory=$true,
HelpMessage="Insert Message")]
[ValidateNotNullOrEmpty()]
$InputObject,
[Parameter(Position=1,
Mandatory=$false,
HelpMessage="Insert Preferred Folder")]
$folder,
[Parameter(Position=2,
Mandatory=$false,
HelpMessage="Insert Preferred Target Datastore")]
$datastore,
[Parameter(Position=3,
Mandatory=$false,
HelpMessage="Insert Preferred Target Host")]
$vmhost,
[Parameter(Position=4,
Mandatory=$false,
HelpMessage="Insert Preferred Disk Storage Format")]
[ValidateSet("Thick","Thin")]
$format = "Thin"
)
PROCESS{
$InputObject | %{
$vm = Get-VM $_
$name = $vm.name
$newname = -join("clone-",$name)
$date = get-date -uformat "-%Y-%m-%d"
$templatename = -join("template-",$name,$date)
If ($datastore -eq $null){
$datastore = Get-Datastore -VM $vm
}
If ($folder -eq $null){
$folder = $vm.Folder
}
If ($vmhost -eq $null){
$vmhost = Get-Cluster -VM $vm | Get-VMHost | Get-Random | Where{$_ -ne $null}
}
Write-Host "VM = $vm"
Write-Host "Name = $name"
Write-Host "NewName = $newname"
Write-Host "DataStore = $datastore"
Write-Host "Folder = $folder"
Write-Host "VMHost = $vmhost"
write-Host "templatename=$templatename"
sleep 4
Write-Host "Setting up domain unjoin script..."
Remove-Item "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "netdom remove $name /Force"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "netdom renamecomputer $name /newname:XA6TEMPLATE /Force"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "REG ADD `"HKEY_LOCAL_MACHINE\SYSTEM\Setup\Status\SysprepStatus`" /v `"GeneralizationState`" /t
REG_DWORD /d 0x7 /f"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "REG ADD `"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
\SoftwareProtectionPlatform`" /v `"SkipRearm`" /t REG_DWORD /d 0x1 /f"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "`"C:\Program Files (x86)\Citrix\XenApp\ServerConfig\XenAppConfigConsole.exe`"
/ExecutionMode:ImagePrep /PrepMsmq:True"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "shutdown -s -t 90 -f"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "del /q `"c:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd"
Write-Host "Setting Autologon..."
psexec \\$name "REG.EXE" ADD `"\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`" /v `"DefaultUserName`" /d Administrator /f`"
sleep 5
psexec \\$name "REG.EXE" ADD `"\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`" /v `"DefaultPassword`" /d Hello /f`"
sleep 5
psexec \\$name "REG.EXE" ADD `"\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`" /v `"AutoAdminLogon`" /t REG_DWORD /d 0x1 /F`"
sleep 5
psexec \\$name "REG.EXE" ADD `"\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon`" /v `"AutoLogonCount`" /t REG_DWORD /d 0x1 /F`"
Write-Host "Cloning"
New-VM -Name $newname -VM $vm -Location $folder -Datastore $datastore -VMHost $vmhost -DiskStorageFormat $format
Write-Host "Unplugging NIC..."
get-VM $newname | get-networkadapter | set-networkadapter -startconnected:$false -confirm:$false
Write-Host "Starting VM..."
start-vm $newname
Write-Host "Powering on clone..."
Remove-Item "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd"
Write-Host "We need to wait until the clone is powered off before we can template it..."
do {
sleep 1.0
Write "Waiting for shutdown of VMs"
} until (Get-VM $newname | Where { $_.PowerState -eq "poweredOff" })
write-host "System is powered on"
Write-Host "Creating NIC..."
get-VM $newname | get-networkadapter | set-networkadapter -startconnected:$true -confirm:$false
Write-Host "Removing any stale template-VM's"
remove-template $templatename -confirm:$false
Write-Host "Creating Template VM from clone"
new-template -VM $newname -name $templatename -Location $folder
Write-Host "Removing Clone VM"
remove-vm $newname -DeletePermanently -confirm:$false
}
}
}
This script does the following:
1) Sets the inputs from a piped in object (get-vm VMTOTEMPLATE | create-template)
2) Sets a series of variables ($vm, $name, $newname, $date, $templatename, etc.)
3) We setup a startup script on the target server to make into a template that:
a) Removes the computer from the domain
b) renames the computer to a generic name (XATEMPLATE)
c) Adds registry keys that will allow sysprep to run
d) Configures XenApp to "Image" mode
e) Shuts itself down once running the script is complete
f) deletes the script from running on startup
4) We then set the target to autologin with the local admin user name and password so the startup script in step 3 will be run
5) Begins the cloning by making a new-vm with the target machine
6) We unplug the NIC from VMWare so that when it starts up the script won't actually remove the machine from the domain, but will remove itself from the domain
7) start the clone
8) the PowerCLI will now wait till the machine turns itself off...
9) Then it will reconnect the NIC, remove any stale templates and then makes a new template and then removes the clone VM.
Done! :)
Citrix IMA service issues
If Citrix is giving you grief because IMA won't start after unjoining and rejoining a farm, do the following:
IMA Service Fails to Start and MFCOM Service Hangs in a Starting State
Document ID: CTX127922 / Created On: 20-Jan-2011 / Updated On: 20-Oct-2011
Average Rating: (5 ratings)
View products this document applies to
Symptoms
IMA Service fails to start and MFCOM Service hangs in a Starting state.
Event ID: 7024
The Independent Management Architecture service terminated with service-specific error: 2147483649 (0x80000001).
- Or –
The IMA service terminated with service-specific error: 2147483647
Cause
When looking into the services manager, the MFCOM Service is in status “starting”. MFCOM and IMA Service fail to start because of a corrupt radeoffline DB.
Note: This issue also occurs after an incomplete or corrupted install of a Citrix Hotfix. Make sure you terminate the MFCOM32.exe as instructed below and re-install the hotfix properly. This can also ensure that the MFCOM Service will start successfully.
Resolution
Stop the mfcom.exe service using Task Manager.
Execute the following commands:
Dsmaint recreatelhc
Dsmaint recreaterade
Start the IMA Service and MFCOM Service.
IMA Service Fails to Start and MFCOM Service Hangs in a Starting State
Document ID: CTX127922 / Created On: 20-Jan-2011 / Updated On: 20-Oct-2011
Average Rating: (5 ratings)
View products this document applies to
Symptoms
IMA Service fails to start and MFCOM Service hangs in a Starting state.
Event ID: 7024
The Independent Management Architecture service terminated with service-specific error: 2147483649 (0x80000001).
- Or –
The IMA service terminated with service-specific error: 2147483647
Cause
When looking into the services manager, the MFCOM Service is in status “starting”. MFCOM and IMA Service fail to start because of a corrupt radeoffline DB.
Note: This issue also occurs after an incomplete or corrupted install of a Citrix Hotfix. Make sure you terminate the MFCOM32.exe as instructed below and re-install the hotfix properly. This can also ensure that the MFCOM Service will start successfully.
Resolution
Stop the mfcom.exe service using Task Manager.
Execute the following commands:
Dsmaint recreatelhc
Dsmaint recreaterade
Start the IMA Service and MFCOM Service.
Wednesday, February 29, 2012
Issue with Folder Redirection (Error %%267)
So we were having an issue with Folder Redirection today with a user. We were moving them from a fileshare to a UNC path. The difference is a file share is explicitly shared, the userdirs$ is a share that then has a folder within.
This was the error in fdeploy.log (enabled here).
%%267. After some brief investigation it was found this users had a huge My Docs and it was copied to the new server. The old directory was then renamed (user1.old) and a new directory was created called user1 and reshared as user1$ on the old server. Then this issue occurred. The reason this issue occurred was because the user wasn't assigned any permissions on the old directory so it was erroring out. I don't know if %%267 is a permission code or not but that's what we found. By adding the user to the folder \\oldserver\user1$ as full control did it then proceed and migrate his My Docs correctly.
This was the error in fdeploy.log (enabled here).
16:32:10:116 Homedir redirection path %HOMESHARE%%HOMEPATH% expanded to \\newserver\userdirs$\user1.
16:32:10:116 Redirecting folder My Documents to \\%HOMESHARE%%HOMEPATH%.
16:32:10:116 Previous folder path \\oldserver\user1$ expanded to \\oldserver\user1$.
16:32:10:116 New folder path \\%HOMESHARE%%HOMEPATH% expanded to \\newserver\userdirs$\user1.
16:32:11:007 Failed to perform redirection of folder My Documents.
The folder is configured to be redirected from <\\oldserver\user1$> to <\\newserver\userdirs$\user1>.
The following error occurred:
%%267
%%267. After some brief investigation it was found this users had a huge My Docs and it was copied to the new server. The old directory was then renamed (user1.old) and a new directory was created called user1 and reshared as user1$ on the old server. Then this issue occurred. The reason this issue occurred was because the user wasn't assigned any permissions on the old directory so it was erroring out. I don't know if %%267 is a permission code or not but that's what we found. By adding the user to the folder \\oldserver\user1$ as full control did it then proceed and migrate his My Docs correctly.
Thursday, February 16, 2012
Registry keys needed to set a default server Exchange server for Outlook
We recently upgraded our Exchange infrastructure from 2007 to 2010. During this we changed the host name of the server from an internal name to a nice, easy to remember one (outlook.company.corp). But, we did not update our Outlook's defaults to this server, so when you open Outlook for the first time you are presented with this message:
Microsoft Exchange is unavailable.
With the options:
Retry, Work Offline, and Cancel. If you choose Work Offline you are given this error message:
"---------------------------
Microsoft Office Outlook
---------------------------
Outlook cannot log on. Verify you are connected to the network and are using the proper server and mailbox name. The connection to Microsoft Exchange is unavailable. Outlook must be online or connected to complete this action.
---------------------------
OK
---------------------------
"
then the opportunity to enter the server name to connect to:
If you correct the name here you will get an error where you can close Outlook then reopen it for it to operate. Another option is to change the default of that server to the correct one. I figured out the registry keys to do those so you can place in a GPO object.
Here are the keys:
The last key is a REG_BINARY of the server name (outlook.company.corp). If we make this into a GPO object then these keys can be placed in and users can connect to Exchange without the messages above.
The GPO object needs to look like so:
Notice the %LogonUser% variable.
Each "Key Path" requires your username substituted for the %LogonUser% variable as well:
Set this GPO with a loopback processing setting and you're rolling. The negative that I've seen with this approach is that it will set the registry keys on a new login, but launching Outlook for the first time will overwrite them with the defaults set in the PRF. If you cancel out and relaunch the registry keys will apply again and the server you specified in them will work.
Or you can setup a DNS Alias, but this was an interesting exercise anyways :)
Microsoft Exchange is unavailable.
With the options:
Retry, Work Offline, and Cancel. If you choose Work Offline you are given this error message:
"---------------------------
Microsoft Office Outlook
---------------------------
Outlook cannot log on. Verify you are connected to the network and are using the proper server and mailbox name. The connection to Microsoft Exchange is unavailable. Outlook must be online or connected to complete this action.
---------------------------
OK
---------------------------
"
then the opportunity to enter the server name to connect to:
If you correct the name here you will get an error where you can close Outlook then reopen it for it to operate. Another option is to change the default of that server to the correct one. I figured out the registry keys to do those so you can place in a GPO object.
Here are the keys:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\ttye\8fa3465791d2b746a2c7d11ca063b282]
"001e660c"="outlook.company.corp"
[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\ttye\406169da1432914e8075fa26cbcdc53a]
"001e660c"="outlook.company.corp"
[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\ttye\1e8559cf990bb44792093b0cdfca0186]
"001e660c"="outlook.company.corp"
[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\ttye\13dbb0c8aa05101a9bb000aa002fc45a]
"001e6602"="outlook.company.corp"
[HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\ttye\dca740c8c042101ab4b908002b2fe182]
"001f662a"=hex:6f,00,75,00,74,00,6c,00,6f,00,6f,00,6b,00,2e,00,63,00,63,00,73,\
00,2e,00,63,00,6f,00,72,00,70,00,00,00
The last key is a REG_BINARY of the server name (outlook.company.corp). If we make this into a GPO object then these keys can be placed in and users can connect to Exchange without the messages above.
The GPO object needs to look like so:
Notice the %LogonUser% variable.
Each "Key Path" requires your username substituted for the %LogonUser% variable as well:
Set this GPO with a loopback processing setting and you're rolling. The negative that I've seen with this approach is that it will set the registry keys on a new login, but launching Outlook for the first time will overwrite them with the defaults set in the PRF. If you cancel out and relaunch the registry keys will apply again and the server you specified in them will work.
Or you can setup a DNS Alias, but this was an interesting exercise anyways :)
Wednesday, February 15, 2012
Purposeful limitations
I have a Citrix environment without a provisioning server. This means that since I'm going to build my VM's out as opposed to up I need to script a method to automate deployment of Citrix servers within the VM environment. Fortunately, VMWare gives us the PowerCLI. A PowerShell that you can use to manipulate VMWare.
While I was working on this I ran into some some weird issues while working with VMWare and deploying OS Customizations.
It turns out if you burn your 3 activations VMWare cannot customize the OS anymore from VMWare. BUT(!) there is a dirty little trick that works for Server 2008 R2 (only one I've tested anyhow) that can allow you to work around the issue. The issue is VMWare's OS Customizations does a Generalize pass using Sysprep. If you exceed the 3 activations, sysprep will fail because it will notice this at the Generalize pass. The solution that I've read is to add this line to the sysprep.xml file:
http://support.microsoft.com/kb/929828
Unfortunately, VMWare does not appear to have a way to allow you to add the SkipRearm to the XML that it generates through the OS Customization GUI. But you can add a couple of registry keys that appear to have the same effect. They are:
These two keys will signal to sysprep that this image can be generalized even though it has exceeded its activation count.
So, what I've found is you need to set these registry keys *prior* to shutting it down to convert into a template. Then when you deploy from template and it starts up and engages sysprep, sysprep will run without issue.
So how do you put this all together? Here is my scenario:
We do NOT have a golden image template of our Citrix environment. This is because it is incredibly fluid. Changes occur to applications on the servers fairly regularly and documentation/memory is difficult to ensure that when we commit to putting these changes into the template that they are actually done. So how are we going to do this? We are going to take a 3 prong approach:
1) We have a dev environment where developers can modify/change and generally mess up their VM's to their hearts content. The whole goal of this environment is to get their application working at 100%. The developers do not need to answer to anyone and have free reign to modify and experiment.
2) We have a test environment where, when the developers think the application is tweaked/modified/configured exactly right; will pass off documentation to me to install in this environment. Any errors or modifications that happen outside of their documentation will be further documented and verified.
3) Once step two is validated we can then push on to install on the production servers.
The issues we encounter is some of our application installs are huge, multi-step non-automated processes with large configuration tweaks post install. Once we get a solid install on one of the production servers our perferred method of redployment (because I've automated this process thus eliminating possible failure points) will be to template and redeploy with VMWare. This is the script I've written to accomplish this:
I've shamelessly stolen and modified this script from elsewhere. To execute this script, copy and paste it in a PowerGUI prompt then run:
It will execute the following:
1) Pull the following parameters from the target VM to reclone:
The VM Object
The VM Objects Name
The New Name for the temp clone
A Template Name
The Datastore the VM resides on
The folder the VM resides in
And the VM Host
2) We then copy a script to our target machine that does the following:
Removes the machine from the domain
Renames the machine
Prepares the addition of our two Sysprep registry key fixes
Prepares a 20 second count down
Deletes the script that executes step 2.
3) We add the default username and password and autologon registry values. As of this writting this is not working for some reason
4) We execute the command that preps the machine for cloning with Citrix. The machine you run this against will need to be rebooted as this will prevent new logons, but existing should continue (I think).
5) We start the cloning process and unplug the NIC on the new machine. We don't want the new machine to come up and unjoin the original machine from the domain. From here, it will auto-power on. Ideally, it will login automatically and run the preconfigured script. (You may have to login manually to get it to do its thing) Once done it should shut itself down.
6) Now VMWare will wait until the machine is powered off. Once it's powered off it will reconnect the NIC and make a template out of the VM and delete the temporary clone.
7) Lastly it will now setup the OS Customization dynmically and create a VM with it.
Voila!
While I was working on this I ran into some some weird issues while working with VMWare and deploying OS Customizations.
It turns out if you burn your 3 activations VMWare cannot customize the OS anymore from VMWare. BUT(!) there is a dirty little trick that works for Server 2008 R2 (only one I've tested anyhow) that can allow you to work around the issue. The issue is VMWare's OS Customizations does a Generalize pass using Sysprep. If you exceed the 3 activations, sysprep will fail because it will notice this at the Generalize pass. The solution that I've read is to add this line to the sysprep.xml file:
1
http://support.microsoft.com/kb/929828
Unfortunately, VMWare does not appear to have a way to allow you to add the SkipRearm to the XML that it generates through the OS Customization GUI. But you can add a couple of registry keys that appear to have the same effect. They are:
REG ADD "HKEY_LOCAL_MACHINE\SYSTEM\Setup\Status\SysprepStatus" /v "GeneralizationState" /t REG_DWORD /d 0x7 /f"
REG ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform" /v "SkipRearm" /t REG_DWORD /d 0x1 /f"
These two keys will signal to sysprep that this image can be generalized even though it has exceeded its activation count.
So, what I've found is you need to set these registry keys *prior* to shutting it down to convert into a template. Then when you deploy from template and it starts up and engages sysprep, sysprep will run without issue.
So how do you put this all together? Here is my scenario:
We do NOT have a golden image template of our Citrix environment. This is because it is incredibly fluid. Changes occur to applications on the servers fairly regularly and documentation/memory is difficult to ensure that when we commit to putting these changes into the template that they are actually done. So how are we going to do this? We are going to take a 3 prong approach:
1) We have a dev environment where developers can modify/change and generally mess up their VM's to their hearts content. The whole goal of this environment is to get their application working at 100%. The developers do not need to answer to anyone and have free reign to modify and experiment.
2) We have a test environment where, when the developers think the application is tweaked/modified/configured exactly right; will pass off documentation to me to install in this environment. Any errors or modifications that happen outside of their documentation will be further documented and verified.
3) Once step two is validated we can then push on to install on the production servers.
The issues we encounter is some of our application installs are huge, multi-step non-automated processes with large configuration tweaks post install. Once we get a solid install on one of the production servers our perferred method of redployment (because I've automated this process thus eliminating possible failure points) will be to template and redeploy with VMWare. This is the script I've written to accomplish this:
function Clone-List{
Param(
[CmdletBinding()]
[Parameter(ValueFromPipeline=$true,
Position=0,
Mandatory=$true,
HelpMessage="Insert Message")]
[ValidateNotNullOrEmpty()]
$InputObject,
[Parameter(Position=1,
Mandatory=$false,
HelpMessage="Insert Preferred Folder")]
$folder,
[Parameter(Position=2,
Mandatory=$false,
HelpMessage="Insert Preferred Target Datastore")]
$datastore,
[Parameter(Position=3,
Mandatory=$false,
HelpMessage="Insert Preferred Target Host")]
$vmhost,
[Parameter(Position=4,
Mandatory=$false,
HelpMessage="Insert Preferred Disk Storage Format")]
[ValidateSet("Thick","Thin")]
$format = "Thin"
)
PROCESS{
$InputObject | %{
$vm = Get-VM $_
$name = $vm.name
$newname = -join("clone-",$name)
$templatename = -join("template-",$name)
If ($datastore -eq $null){
$datastore = Get-Datastore -VM $vm
}
If ($folder -eq $null){
$folder = $vm.Folder
}
If ($vmhost -eq $null){
$vmhost = Get-Cluster -VM $vm | Get-VMHost | Get-Random | Where{$_ -ne $null}
}
Write-Host "VM = $vm"
Write-Host "Name = $name"
Write-Host "NewName = $newname"
Write-Host "DataStore = $datastore"
Write-Host "Folder = $folder"
Write-Host "VMHost = $vmhost"
Write-Host "Setting up domain unjoin script..."
Remove-Item "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "netdom remove $name /Force"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "netdom renamecomputer $name /newname:XA6TEMPLATE /Force"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "REG ADD `"HKEY_LOCAL_MACHINE\SYSTEM\Setup\Status\SysprepStatus`" /v `"GeneralizationState`" /t REG_DWORD /d 0x7 /f"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "REG ADD `"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform`" /v `"SkipRearm`" /t REG_DWORD /d 0x1 /f"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "shutdown -s -t 20 -f"
Add-Content "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd" "del /q `"c:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd"
Write-Host "Setting Autologon..."
REG ADD "\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v "DefaultUserName" /d Administrator /f
REG ADD "\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v "DefaultPassword" /d 'password123' /f
REG ADD "\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v "AutoAdminLogon" /t REG_DWORD /d 0x5 /F
REG ADD "\\$name\HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v "AutoLogonCount" /t REG_DWORD /d 0x1 /F
Write-Host "Preparing XenApp for Cloning..."
psexec \\$name "C:\Program Files (x86)\Citrix\XenApp\ServerConfig\XenAppConfigConsole.exe" /ExecutionMode:ImagePrep /PrepMsmq:True
Write-Host "Cloning"
New-VM -Name $newname -VM $vm -Location $folder -Datastore $datastore -VMHost $vmhost -DiskStorageFormat $format
Write-Host "Unplugging NIC..."
get-VM $newname | get-networkadapter | set-networkadapter -startconnected:$false -confirm:$false
Write-Host "Starting VM..."
start-vm $newname
Write-Host "Powering on clone..."
REG ADD "\\$name\HKLM\SYSTEM\Setup\Status\SysprepStatus" /v "GeneralizationState" /t REG_DWORD /d 0x3 /f
Remove-Item "\\$name\c$\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\remove.cmd"
REG DELETE "\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v "DefaultUserName" /f
REG DELETE "\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v "DefaultPassword" /f
REG DELETE "\\$name\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v "AutoAdminLogon" /f
REG DELETE "\\$name\HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon" /v "AutoLogonCount" /f
Write-Host "We need to wait until the clone is powered off before we can template it..."
do {
sleep 1.0
Write "Waiting for shutdown of VMs"
} until (Get-VM $newname | Where { $_.PowerState -eq "poweredOff" })
write-host "System is powered on"
Write-Host "Creating NIC..."
get-VM $newname | get-networkadapter | set-networkadapter -startconnected:$true -confirm:$false
Write-Host "Removing any stale template-VM's"
remove-template $templatename -confirm:$false
Write-Host "Creating Template VM from clone"
new-template -VM $newname -name $templatename -Location $folder
Write-Host "Removing Clone VM"
remove-vm $newname -DeletePermanently -confirm:$false
Write-Host "Setting up OS customization"
$cs = Get-OSCustomizationSpec PowerCLI
Set-OSCustomizationSpec -OSCustomizationSpec PowerCLI -ChangeSID:$true -Domain CCS.CORP -DomainUsername admin-ttye -DomainPassword password123 -NamingScheme Fixed -NamingPrefix CDCVXAP03P
new-vm -VMHost (Get-Cluster -VM $vm | Get-VMHost | Get-Random | Where{$_ -ne $null}) -name CDCVXAP03P -Template template-CDCVXAP02P -Datastore $datastore -OSCustomizationSpec $cs
get-VM CDCVXAP03P | get-networkadapter | set-networkadapter -startconnected:$true -confirm:$false
}
}
}
I've shamelessly stolen and modified this script from elsewhere. To execute this script, copy and paste it in a PowerGUI prompt then run:
get-vm CDCVXAP02P | Clone-List
It will execute the following:
1) Pull the following parameters from the target VM to reclone:
The VM Object
The VM Objects Name
The New Name for the temp clone
A Template Name
The Datastore the VM resides on
The folder the VM resides in
And the VM Host
2) We then copy a script to our target machine that does the following:
Removes the machine from the domain
Renames the machine
Prepares the addition of our two Sysprep registry key fixes
Prepares a 20 second count down
Deletes the script that executes step 2.
3) We add the default username and password and autologon registry values. As of this writting this is not working for some reason
4) We execute the command that preps the machine for cloning with Citrix. The machine you run this against will need to be rebooted as this will prevent new logons, but existing should continue (I think).
5) We start the cloning process and unplug the NIC on the new machine. We don't want the new machine to come up and unjoin the original machine from the domain. From here, it will auto-power on. Ideally, it will login automatically and run the preconfigured script. (You may have to login manually to get it to do its thing) Once done it should shut itself down.
6) Now VMWare will wait until the machine is powered off. Once it's powered off it will reconnect the NIC and make a template out of the VM and delete the temporary clone.
7) Lastly it will now setup the OS Customization dynmically and create a VM with it.
Voila!