So our department a while ago was asked about getting some iPads..DUN! DUN! DAHHH
yep its all fun and games till we asked for an actual real word use for them that a laptop couldn't do. I don't have problem with the iPad as a device per-say but don't really see very many valid business uses for them ontop of the fact that they are a down right pain in the ass to manage both Policy wise and User wise. Yeh don't try and pretend like its easy.... its still easier to manage full fledged computers so don't even bother arguing fanbois.
Anyway off topic a little, we ended up buying a whole raft of different computers to let them choose from, including the Acer Iconia Tab W501, which was running Windows 7. Honestly? it was horrible. The touch was horrbile, it was unbelievably slow and just a pain to use so when the Windows 8 Dev Preview we jumped on board and installed it on the Iconia straight away.
BEST THING EVER...
It was pretty funny the fact that a Dev Preview ie pre-beta Windows 8 OS was nicer on the touch interface than the Windows 7 machine, but who are we to argue. The other big plus was the much faster boot times. Windows 7 took roughly 5 minutes to boot on the Iconia, including logins. The Win 8 Preview took under a minute from startup to login. All in all we where very impressed.
The Consumer Preview has now come out for Windows 8 now and is even nicer to use on the Icionia than the Dev Preview. Its clear that Microsoft has put alot of work into startup times and the touch interface is really very nice.
It was no mean feat to install the Windows 8 on the Iconia either. What would seem like a simple task was actually a bit of a pain in the umm hmm finger?
So we start with downloading.
If you already have the Dev Preview installed you can go here and download the Windows 8 Consumer Executable file which you simply run on the Dev Preview and Viola! you have now upgraded to the Consumer Edition of Windows 8. Ignore everything below this :P
A Clean install is a little more fun. First you want to download the Windows 8 Consumer ISO file here and extract the iso into a folder once it has finished downloading. If you are doing this for the Acer Iconia, x64 runs well on it.
The Serial Key you will need for the install is DNJXJ-7XBW8-2378T-X22TX-BKG7J
Next we need to make a bootable thumbdrive since out Iconia doesn't have DVD-ROM. The Thumb drive needs to be a minimum of 4GB.
We will need to download the Windows AIK(Automated Installation Kit) from here
and install it onto the computer.
Use the following commands to format a USB and make it bootable to install Windows 8 from.
All commands are without quotes
- Plug the thumb drive in. Make sure there is nothing on it you want to keep because we are going to need to format it.
- Start the Deployment Tools Command Prompt which is installed with the AIK
- "diskpart"
- "list disk"
This will display a list of disks which are currently connected to your computer, including your thumb drive. Look at the sizes listed to determine which of the drive numbers is the thumb drive
ie
In this list we can see that the thumb drive I am using is a 16GB(listed as 14GB) Disk number 2
In the following examples I will be using "Disk 2". you will need to substitute the relevant disk number in-place of Disk 2
- "sel disk 2"
***Warning***
This will format and delete all the contents on the thumbdrive, there is no turning back if you have anything on it you want to keep after this command
- "clean"
ie
- "create part primary"
- "format fs=ntfs quick label=BOOT"
- "active"
After this a new Thumb Drive should popup on the computer, in my case drive letter "L:"
ie
In the following examples I will be using Drive Letter "L:". You will need to substitute the relevant letter for your computer.
- "exit"
- "cd amd64" or "cd x86" based off whether you are using the x64 installer or x86 installer
- "bootsect /nt60 L:"
ie
The thumb drive should now be bootable and ready to copy the extracted Windows files from the ISO onto the thumb drive. That's not ISO onto the thumb drive.... Extract the ISO and copy all the contents onto the thumb drive. It should look something like this once is all copied to the thumb drive.
ie
Don't forget to remove the thumb drive safely from the computer. Since the thumb drive is now using an NTFS partition we can't have any more of that RIP THAT PUPPY OUT SHEEL BE RIGHT!! because it will break it the partition and make it unbootable.
Turn the Iconia off and if you have a Dock, take it off the dock and plug in a USB Keyboard and Thumb Drive. Funny stuff they make a dock that doesn't work properly in the BIOS :) Hold the Windows button on the Iconia and Turn it on while pressing the F2 key. If your like me you will need another person to help you with this.
Change the USB drive to be first boot, save the BIOS and reboot.
Here is a link to the Acer Iconia Tab W500 Manual if you want more detailed instructions on getting into the BIOS
*EDIT* I have also had a problem recently with booting off the thumb drive again after Win 8 was installed when I stumbled upon this post
http://www.mayanksrivastava.com/2012/03/installing-windows-8-consumer-preview.html
which fixed the problem for me
I tip my hat to you
Also Drivers are now available at Acer for Win 8
http://support.acer.com/us/en/product/default.aspx?tab=1&modelId=3853
You will now be able to run the Windows 8 Consumer Preview from the Thumb Drive. Happy installing!
Wednesday, 29 February 2012
Wednesday, 15 February 2012
You can add the logging in user as a local admin? Thats impossabarble!
The debate had gone on for a long time as to whether we should allow users to have local admin rights on there computer. Where I currently work it is a requirement to allow users to have local admin rights over there computer but then that raised the interesting question of how do you secure the network and/or devices where you do give them local admin rights?
Alot of people simply add Domain Users to the Administrators group on the local computer to give there domain users local admin rights. This also unfortunately give the user local admin rights on every other computer in the school also so what can be done about this?
Besides the obligatory GPO settings to limit the amount of access a user has at a local admin level over another computer across the network, we also came up with the solution of only giving local admin rights to a user which has logged into a computer. ie as they login to a computer at a user level they will be granted local admin rights with a login script. I already here you thinking to yourself "but they are at a user level. They can't give themselves local admin rights!" and you are right, you cant give yourself local admin rights if you are logged in as a normal user, thus the fun-ness of this script :)
I wrote the script to check to see if it has admin rights, if it doesn't, to re-run the script under different user permissions to allow the local user to be added to the Administrators.
as always before we start :P
[Rant]Now before we get started on the scripting lets get one thing straight,
simply add the powershell script to start and login, and viola! you will now have users granted local admin rights at login. For the astute people that noticed(so I bet no one) you will notice the script actually checks to see if there is a Domain Users group under local admin and if so removes it then adds the user and your probably thinking whats the point in that?
The one problem with this script is that if you are logging in as a user you will not have local admin rights unless you logoff the computer then back on as you have started that login session as a normal user and the effect of being in the local admin group will not be picked up until the next login. Since the majority of our school is 1 Device to 1 User we add Domain Users to the local admin group in our SOE which means the first user login will be granter admin rights on the computer without having to logoff and in again and the Domain Users group will be removed from the local admin group.
The Username and Password used to run the script at elevated privileges should be added to the local admin group of all computers and should have absolutely no network access to anything except to add the local user to the local administrator group. This means even if they get the username and password of the user, they are still limited in what they can actually do with it.
To encrypt the password for the user in the script you can use the following
Alot of people simply add Domain Users to the Administrators group on the local computer to give there domain users local admin rights. This also unfortunately give the user local admin rights on every other computer in the school also so what can be done about this?
Besides the obligatory GPO settings to limit the amount of access a user has at a local admin level over another computer across the network, we also came up with the solution of only giving local admin rights to a user which has logged into a computer. ie as they login to a computer at a user level they will be granted local admin rights with a login script. I already here you thinking to yourself "but they are at a user level. They can't give themselves local admin rights!" and you are right, you cant give yourself local admin rights if you are logged in as a normal user, thus the fun-ness of this script :)
I wrote the script to check to see if it has admin rights, if it doesn't, to re-run the script under different user permissions to allow the local user to be added to the Administrators.
as always before we start :P
[Rant]Now before we get started on the scripting lets get one thing straight,
I AM NOT A PROGRAMMER!!
Yes there will be a better way of doing it, could I make it work? no so
if you can make it work feel free to make a post and I will change the
script :) [/Rant]$pathTemp = "C:\Temp\Login.tmp"
$password = "lotsofnumbersandlettersinheretotisthepasswordinitsecryptedformandiwllpostthescriptandtalkaboutitlaterintheblogandyesitreallyisthislongimademine256ithinkohhandthekeyisover9000"
$key = "111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111 111"
$domain = "domain"
$strComputer = "$env:computername"
#downloaded from http://gallery.technet.microsoft.com/scriptcenter/63fd1c0d-da57-4fb4-9645-ea52fc4f1dfb/
function Test-Admin {
$currentPrincipal = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent() )
if ($currentPrincipal.IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator )) {
return $true
}
else {
return $false
}
}
#downloaded from http://myitforum.com/cs2/blogs/yli628/archive/2007/08/30/powershell-script-to-add-remove-a-domain-user-to-the-local-administrators-group-on-a-remote-machine.aspx
function AddLocal {
if(Test-Path $pathTemp){
$username = Get-Content $pathTemp
}
$computer = [ADSI]("WinNT://" + $strComputer + ",computer")
$Group = $computer.psbase.children.find("administrators")
$Group.Add("WinNT://" + $domain + "/" + $username)
Remove-Item $pathTemp -Force
break
}
start-sleep -s 3
$Invocation=(Get-Variable MyInvocation).Value
if ($Invocation.MyCommand.Path -ne $null) {
$arg="-file "+$Invocation.MyCommand.Path
if (!(Test-Admin)) {
Out-File -FilePath $pathTemp -InputObject $env:username -Force
$passwordSecure = ConvertTo-SecureString -String $password -Key ([Byte[]]$key.Split(" "))
$credential = New-Object system.Management.Automation.PSCredential("domain\usertorunas", $passwordSecure)
Start-Process "$psHome\powershell.exe" -Credential $credential -ArgumentList $arg
break
}
else {
if(Test-Path $pathTemp){
$username = Get-Content $pathTemp
AddLocal
}
#downloaded from http://www.powershellcommunity.org/Forums/tabid/54/aft/1528/Default.aspx
$group =[ADSI]"WinNT://./Administrators"
$members = @($group.psbase.Invoke("Members"))
$UsersInGroup= $members | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
foreach($DomainUsers in $UsersInGroup) {
if ($DomainUsers -eq "Domain Users") {
$Group.Remove("WinNT://" + $domain + "/Domain Users")
$username = $env:username
AddLocal
}
}
}
}
simply add the powershell script to start and login, and viola! you will now have users granted local admin rights at login. For the astute people that noticed(so I bet no one) you will notice the script actually checks to see if there is a Domain Users group under local admin and if so removes it then adds the user and your probably thinking whats the point in that?
The one problem with this script is that if you are logging in as a user you will not have local admin rights unless you logoff the computer then back on as you have started that login session as a normal user and the effect of being in the local admin group will not be picked up until the next login. Since the majority of our school is 1 Device to 1 User we add Domain Users to the local admin group in our SOE which means the first user login will be granter admin rights on the computer without having to logoff and in again and the Domain Users group will be removed from the local admin group.
The Username and Password used to run the script at elevated privileges should be added to the local admin group of all computers and should have absolutely no network access to anything except to add the local user to the local administrator group. This means even if they get the username and password of the user, they are still limited in what they can actually do with it.
To encrypt the password for the user in the script you can use the following
# Path to the script to be created:
$path = 'c:\temp\template.ps1'
# Create empty template script:
New-Item -ItemType File $path -Force -ErrorAction SilentlyContinue
$pwd = Read-Host 'Enter Password' -AsSecureString
$user = Read-Host 'Enter Username'
$key = 1..32 | ForEach-Object { Get-Random -Maximum 256 }
$pwdencrypted = $pwd | ConvertFrom-SecureString -Key $key
$private:ofs = ' '
('$password = "{0}"' -f $pwdencrypted) | Out-File $path
('$key = "{0}"' -f "$key") | Out-File $path -Append
'$passwordSecure = ConvertTo-SecureString -String $password -Key ([Byte[]]$key.Split(" "))' |
Out-File $path -Append
('$cred = New-Object system.Management.Automation.PSCredential("{0}", $passwordSecure)' -f $user) |
Out-File $path -Append
'$cred' | Out-File $path -Append
ise $path
# http://powershell.com/cs/media/p/7968.aspx
These scripts do the job fine. The debate of whether we should be giving the local admin rights to users I am sure will continue on for many years to come. I think that as the software changes and the lines between local admins and users blurs even more as it has in Windows 7, this problem will disappear.
Tuesday, 14 February 2012
JSON Why for you hurt my brain so?
You know how I said it would be easy to pull a JSON stream for our portal in my previous blog post?
here I will quote it
So I did get some web code working, but every time I tried putting it on our sharepoint site, it would stop working.
Here is the Code I was using
The Same Origin Policy was the problem. I don't like it :P
So without making the job a whole lot harder I scrapped that method of getting it in sharepoint and chose the most likely dodgiest method ever. I wrote a powershell script which pulls the json data from PaperCut, formats it and dumps it into a static location on the sharepoint server as a html file. Yep that's right a local script on the server :P, I added it to Task Schedueler to run hourly and viola! a simple formatted Total Environmental Impact page in the portal.
Here is the powershell code i used
ohh and my obligatory disclaimer
[Rant]Now before we get started on the scripting lets get one thing straight,
Since its a simple HTML page, you can embedded it into sharepoint and put pretty graphics around it etc etc and your done :)
here I will quote it
"The local sharepoint portal display will be very easy to implement once a gadget has been made to interpret a JSON stream which the Paper Cut server makes available and has the added bonus of showing the total impact throughout the entire schools printing."Yep well its not. In fact it made my brain hurt. ALLOT.
So I did get some web code working, but every time I tried putting it on our sharepoint site, it would stop working.
Here is the Code I was using
<html>It worked fine on the papercut server itself. It showed the number of trees that had been cut down as a percentage, as it is in the JSON data. But would not work on the sharepoint site. I posted it on the MITIE forum and with a few replys, Kane Rogers from Bluereef (shameless plug, we don't even use bluereef so i was pretty impressed that Kane helped me as much as he did) mentioned the answer when i sent him my code.
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js"></script>
<script type="text/javascript">
$("document").ready(function () {
$.getJSON('http://papercut:9191/rpc/api/web/print-stats.json', function (data) {
$("#PaperCut").html('');
$.each (data.items, function (i, item) {
$("#PaperCut").append('<div class="print-stats"><div class="TreesFormatted">' + item.TreesFormatted </div><div class="clear"></div>');
});
});
$("#PaperCut").fadeIn(1000);
});
</script>
<div class="main">
<div id="PaperCut"><img src="images/ajax-loader.gif" alt="Loading..." /></div>
</div>
</body>
</html>
The Same Origin Policy was the problem. I don't like it :P
So without making the job a whole lot harder I scrapped that method of getting it in sharepoint and chose the most likely dodgiest method ever. I wrote a powershell script which pulls the json data from PaperCut, formats it and dumps it into a static location on the sharepoint server as a html file. Yep that's right a local script on the server :P, I added it to Task Schedueler to run hourly and viola! a simple formatted Total Environmental Impact page in the portal.
Here is the powershell code i used
ohh and my obligatory disclaimer
[Rant]Now before we get started on the scripting lets get one thing straight,
I AM NOT A PROGRAMMER!!
Yes there will be a better way of doing it, could I make it work? no so
if you can make it work feel free to make a post and I will change the
script :) [/Rant]# the json sourceNo error checking because well, does it really matter if it breaks? I guess you could put some trap exits if you felt the need.
$source = "http://papercut:9191/rpc/api/web/print-stats.json"
# temp location to save the json file
$pathTemp = "C:\Temp\temp.json"
# location to save the html file
$pathSave = "C:\inetpub\wwwroot\PaperCut\PaperCut.html"
# webget request for the file
$wc = New-Object System.Net.WebClient
$wc.DownloadFile($source, $pathTemp)
# dumps the json file into an array spliting it via the ","
$jsonString = Get-Content $pathTemp
$jsonArray = $jsonString.split(",")
# Total Trees used
# grabs the invidual array item and splits it again using the ":"
$jsonTree = $jsonArray[2].split(":")
# Removes the " from around the value
$jsonTreeString = $jsonTree[1].Replace("`"", "")
# Total CO2 Produced
# grabs the invidual array item and splits it again using the ":"
$jsonCO = $jsonArray[3].split(":")
# Removes the " from around the value
$jsonCOString = $jsonCO[1].Replace("`"", "")
# Total No of hours a 60W lightbulb could be run
# grabs the invidual array item and splits it again using the ":"
$jsonBulb = $jsonArray[5].split(":")
# Removes the " from around the value
$jsonBulbString = $jsonBulb[1].Replace("`"", "")
# the number got split twice in the array because they used a comma ie 4,000
# which would be 4 as one array item and 000 as the second array item
# so I had to add the second half of the number
$jsonBulbString = $jsonBulbString + ($jsonArray[6].Replace("`"", ""))
# pulls all the values into a single string, including some html tags so it displays in a browser
$htmlString = "<html>" + $jsonTreeString + "<BR>" + $jsonCOString + "<BR>" + $jsonBulbString + "</html>"
# spits out the html file, overwrites the old file if it exists
Out-File -FilePath $pathSave -InputObject $htmlString -Force
Since its a simple HTML page, you can embedded it into sharepoint and put pretty graphics around it etc etc and your done :)
Sunday, 12 February 2012
Forcing Gadgets on a Desktop? COMPUTER SAYS NO!
We recently decided to implement a new software solution for printing called PaperCut to try and decrease the amount of paper wasted through out the school. Although PaperCut does do account balances, crediting and print job releases, we where wanting it more for the monitoring of print jobs and to display a users environmental impact of there printing. This will mean lower maintenance for the IT Department for the new system as we will not be having to credit users as they begin to run low and the ethos of printing will be changed to the users considering the environmental impact of there printing rather than our department being seen as "The Big Bad Wolf".
This is working well, but to display the individual user impact could be done a few different ways:
- Client run on login
- Local web gadget on sharepoint portal
- Win 7 Gadget on the desktop
The local sharepoint portal display will be very easy to implement once a gadget has been made to interpret a JSON stream which the Paper Cut server makes available and has the added bonus of showing the total impact throughout the entire schools printing.
This works well but we also discussed and decided that we wanted something more confronting than a web gadget in the portal to show an immediate consequence to there printing so it was decided to force a Win 7 Gadget onto the desktop of the computers.
I had thought this would have actually been a simple task with the flexibility that has been added to Win 7 with group policies I had assumed this had extend to gadgets also but as I quickly found out, this isn't so.
Pushing a gadget out was not a problem, simply building an MSI using wItem Installer to install a gadget folder that comes with PaperCut to C:\Program Files\Windows Sidebar\Gadgets and viola you can now open and add the Gadget using the right-click menu on the desktop!
To easy, except if you want the gadget to be automagically forced onto the desktop and not allow it to be closed :S That is where fun part came in!
We eventually settled on the fact that you cannot prevent the users from closing the Gadget since we also still wanted to allow users to install and use there own gadgets, as well as still displaying our PaperCut Gadget so we moved on the idea that if it is closed can we make it re-appear?
We ended up writing a small script which checks the gadget ini file and adjusts the file to re-add PaperCut if it has been closed.
The How:
The Gadgets on a Users desktop are Profile dependent and can be found under
C:\Users\%username%\AppData\Local\Microsoft\Windows Sidebar\Settings.ini
The Settings.ini file will change dynamically based off what gadgets are currently being displayed on the desktop.
Below is a blank Settings.ini file
[Root]
SettingsVersion="00.00.00.02"
ShowGalleryPrivacyStatementOnceComplete="true"
[Hashes]
C:\Program Files\Windows Sidebar\Gadgets\PCEnvironmentalImpact.gadget="%7B5E373E6F-DE7E-76D7-A10B-DA294544DC6B%7D"
Once a Gadget has been added to the desktop Settings.ini file changes to
[Root]
SettingsVersion="00.00.00.02"
ShowGalleryPrivacyStatementOnceComplete="true"
Section0="1"
[Hashes]
C:\Program Files\Windows Sidebar\Gadgets\PCEnvironmentalImpact.gadget="%7B5E373E6F-DE7E-76D7-A10B-DA294544DC6B%7D"
[Section 1]
PrivateSetting_GadgetName="C:%5CProgram%20Files%5CWindows%20Sidebar%5CGadgets%5CPCEnvironmentalImpact.gadget"
server.hostName="SERVER"
server.port="9191"
PrivateSetting_GadgetDropLocationX="1520"
PrivateSetting_GadgetDropLocationY="0"
PrivateSetting_GadgetSize="small"
We can see it has added a Root setting Section0="1" which indicates which order the gadget is in with the Section0= .If there is a second gadget this would be Section1= . The "1" indicates [Section 1] of the ini file to tell the gadget where it should pull its settings and location from. The [Hashes] info will now stick in the ini file statically after the gadget was installed using the MSI and will not need to be altered to force the gadget to display on the desktop.
Since we now have all the information that needs to be in the Settings.ini file to display our gadget on the desktop we can now write a script to re-apply these settings if this gadget is ever closed. We have made the script run during login since this software only works while there notebooks are onsite but it could theoretically be made to run on a timed basis to permanently place the gadget on the desktop, even when they are logging in locally.
[Rant]Now before we get started on the scripting lets get one thing straight,
The script has been written in Powershell then used PS2EXE to convert the script into an exe so we can run it through our login script. Even with the wrapper the EXE file is only 32k and runs very quickly.
# file path to the ini file
$fileName = "C:\Users\"+$env:username+"\AppData\Local\Microsoft\Windows Sidebar\Settings.ini"
# folder path to the ini file, the file is locked while in use so Test-Path generates an error thus we use Folder Path to check for Win 7
$filePath = "C:\Users\"+$env:username+"\AppData\Local\Microsoft\Windows Sidebar"
#a variable to loop to check for the section value
$replaceNo = 0
#check if the process need resarting
$ProcessRestart = 0
function PaperCutFun {
#filepath check to make sure this computer can run gadgets
if(Test-Path $filePath){
#Checking to see if the settings are already in the ini
if (!(Get-Content $fileName | Select-String "Section0=`"50`"" -quiet)){
#killing the sidebar.exe if it is running to edit the Settings.ini file
if ((Get-Process sidebar -ea 0)) {
Stop-Process -Force -processname sidebar
#sleeping the kill to give sidebar time to close
sleep -Seconds 5
}
#Searching the Settings.ini file to see if the gadget has been re-opened in a different order, thus causing a duplicate gadget
if (Get-Content $fileName | Select-String "Section0=" -quiet) {
do{
(Get-Content $fileName) |
Foreach-Object {$_ -replace ("Section0=`""+$replaceNo+"`""), "Section0=`"50`""} |
Set-Content $fileName
$replaceNo++
}
while($replaceNo -le 100)
}
#if it hasnt been re-opened, add it back in
else {
(Get-Content $fileName) |
Foreach-Object {$_ -replace "\[Root\]", "[Root]
Section0=`"50`""} |
Set-Content $fileName
}
$ProcessRestart++
}
#Checking to see if the settings are already in the ini
if (!(Get-Content $fileName | Select-String "Section 50" -quiet)) {
#killing the sidebar process to edit the ini
if ((Get-Process sidebar -ea 0)) {
Stop-Process -Force -processname sidebar
}
#adding the Section settings to the ini
Add-Content $fileName ("
[Section 50]
PrivateSetting_GadgetName=`"C:%5CProgram%20Files%5CWindows%20Sidebar%5CGadgets%5CPCEnvironmentalImpact.gadget`"
server.hostName=`"STUDENTFILE`"
server.port=`"9191`"")
$ProcessRestart++
}
#Start the sidebar again if it has had to be killed to edit the ini file
if ($ProcessRestart -ge 1){
#checking to make sure it really is closed before we restart it.
if ((Get-Process sidebar -ea 0)) {
Stop-Process -Force -processname sidebar
}
#start sidebar
Start-Process "C:\Program Files\Windows Sidebar\sidebar.exe"
}
}
}
PaperCutFun
Download
PaperCutDemo.ps1
Add a prompt to start the script, we still use vbs as out login script
' Launch PaperCut Gadget Check
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "\\domain\NETLOGON\papercut.exe", 0
And viola!, even if the gadget is closed, it will now get dumped back onto the desktop.
This is working well, but to display the individual user impact could be done a few different ways:
- Client run on login
- Local web gadget on sharepoint portal
- Win 7 Gadget on the desktop
The local sharepoint portal display will be very easy to implement once a gadget has been made to interpret a JSON stream which the Paper Cut server makes available and has the added bonus of showing the total impact throughout the entire schools printing.
This works well but we also discussed and decided that we wanted something more confronting than a web gadget in the portal to show an immediate consequence to there printing so it was decided to force a Win 7 Gadget onto the desktop of the computers.
I had thought this would have actually been a simple task with the flexibility that has been added to Win 7 with group policies I had assumed this had extend to gadgets also but as I quickly found out, this isn't so.
Pushing a gadget out was not a problem, simply building an MSI using wItem Installer to install a gadget folder that comes with PaperCut to C:\Program Files\Windows Sidebar\Gadgets and viola you can now open and add the Gadget using the right-click menu on the desktop!
To easy, except if you want the gadget to be automagically forced onto the desktop and not allow it to be closed :S That is where fun part came in!
We eventually settled on the fact that you cannot prevent the users from closing the Gadget since we also still wanted to allow users to install and use there own gadgets, as well as still displaying our PaperCut Gadget so we moved on the idea that if it is closed can we make it re-appear?
We ended up writing a small script which checks the gadget ini file and adjusts the file to re-add PaperCut if it has been closed.
The How:
The Gadgets on a Users desktop are Profile dependent and can be found under
C:\Users\%username%\AppData\Local\Microsoft\Windows Sidebar\Settings.ini
The Settings.ini file will change dynamically based off what gadgets are currently being displayed on the desktop.
Below is a blank Settings.ini file
[Root]
SettingsVersion="00.00.00.02"
ShowGalleryPrivacyStatementOnceComplete="true"
[Hashes]
C:\Program Files\Windows Sidebar\Gadgets\PCEnvironmentalImpact.gadget="%7B5E373E6F-DE7E-76D7-A10B-DA294544DC6B%7D"
Once a Gadget has been added to the desktop Settings.ini file changes to
[Root]
SettingsVersion="00.00.00.02"
ShowGalleryPrivacyStatementOnceComplete="true"
Section0="1"
[Hashes]
C:\Program Files\Windows Sidebar\Gadgets\PCEnvironmentalImpact.gadget="%7B5E373E6F-DE7E-76D7-A10B-DA294544DC6B%7D"
[Section 1]
PrivateSetting_GadgetName="C:%5CProgram%20Files%5CWindows%20Sidebar%5CGadgets%5CPCEnvironmentalImpact.gadget"
server.hostName="SERVER"
server.port="9191"
PrivateSetting_GadgetDropLocationX="1520"
PrivateSetting_GadgetDropLocationY="0"
PrivateSetting_GadgetSize="small"
We can see it has added a Root setting Section0="1" which indicates which order the gadget is in with the Section0= .If there is a second gadget this would be Section1= . The "1" indicates [Section 1] of the ini file to tell the gadget where it should pull its settings and location from. The [Hashes] info will now stick in the ini file statically after the gadget was installed using the MSI and will not need to be altered to force the gadget to display on the desktop.
Since we now have all the information that needs to be in the Settings.ini file to display our gadget on the desktop we can now write a script to re-apply these settings if this gadget is ever closed. We have made the script run during login since this software only works while there notebooks are onsite but it could theoretically be made to run on a timed basis to permanently place the gadget on the desktop, even when they are logging in locally.
[Rant]Now before we get started on the scripting lets get one thing straight,
I AM NOT A PROGRAMMER!!
Yes there will be a better way of doing it, could I make it work? no so if you can make it work feel free to make a post and I will change the script :) [/Rant]The script has been written in Powershell then used PS2EXE to convert the script into an exe so we can run it through our login script. Even with the wrapper the EXE file is only 32k and runs very quickly.
# file path to the ini file
$fileName = "C:\Users\"+$env:username+"\AppData\Local\Microsoft\Windows Sidebar\Settings.ini"
# folder path to the ini file, the file is locked while in use so Test-Path generates an error thus we use Folder Path to check for Win 7
$filePath = "C:\Users\"+$env:username+"\AppData\Local\Microsoft\Windows Sidebar"
#a variable to loop to check for the section value
$replaceNo = 0
#check if the process need resarting
$ProcessRestart = 0
function PaperCutFun {
#filepath check to make sure this computer can run gadgets
if(Test-Path $filePath){
#Checking to see if the settings are already in the ini
if (!(Get-Content $fileName | Select-String "Section0=`"50`"" -quiet)){
#killing the sidebar.exe if it is running to edit the Settings.ini file
if ((Get-Process sidebar -ea 0)) {
Stop-Process -Force -processname sidebar
#sleeping the kill to give sidebar time to close
sleep -Seconds 5
}
#Searching the Settings.ini file to see if the gadget has been re-opened in a different order, thus causing a duplicate gadget
if (Get-Content $fileName | Select-String "Section0=" -quiet) {
do{
(Get-Content $fileName) |
Foreach-Object {$_ -replace ("Section0=`""+$replaceNo+"`""), "Section0=`"50`""} |
Set-Content $fileName
$replaceNo++
}
while($replaceNo -le 100)
}
#if it hasnt been re-opened, add it back in
else {
(Get-Content $fileName) |
Foreach-Object {$_ -replace "\[Root\]", "[Root]
Section0=`"50`""} |
Set-Content $fileName
}
$ProcessRestart++
}
#Checking to see if the settings are already in the ini
if (!(Get-Content $fileName | Select-String "Section 50" -quiet)) {
#killing the sidebar process to edit the ini
if ((Get-Process sidebar -ea 0)) {
Stop-Process -Force -processname sidebar
}
#adding the Section settings to the ini
Add-Content $fileName ("
[Section 50]
PrivateSetting_GadgetName=`"C:%5CProgram%20Files%5CWindows%20Sidebar%5CGadgets%5CPCEnvironmentalImpact.gadget`"
server.hostName=`"STUDENTFILE`"
server.port=`"9191`"")
$ProcessRestart++
}
#Start the sidebar again if it has had to be killed to edit the ini file
if ($ProcessRestart -ge 1){
#checking to make sure it really is closed before we restart it.
if ((Get-Process sidebar -ea 0)) {
Stop-Process -Force -processname sidebar
}
#start sidebar
Start-Process "C:\Program Files\Windows Sidebar\sidebar.exe"
}
}
}
PaperCutFun
Download
PaperCutDemo.ps1
Add a prompt to start the script, we still use vbs as out login script
' Launch PaperCut Gadget Check
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "\\domain\NETLOGON\papercut.exe", 0
And viola!, even if the gadget is closed, it will now get dumped back onto the desktop.
Who what when what?
I work as a Network Admin quasi System Admin in a school which teachers K-12 with a notebook program. What this means is I run into weird and wonderful problems that most people in the enterprise world don't see or simply doesn't exist. I decided to make this blog to try and keep a running sheet of problems that I have either solved or simply to post small projects which I have worked on and completed. This is my first attempt at blogging so if you don't like it, feel free to abuse everyone around you and not me. :)
Subscribe to:
Posts (Atom)