5.0.366.0 dev seems to have added pin tab back in. Let’s hope it stays. Thanks Mr. Google.
-
Google Chrome for the Mac – Pin tab is back
-
Powershell signing, makecert.exe and group policy – Part 2
In the previous post I showed how to create self signed signing certs via the makecert tool. Once I made the pfx files, and signed my script, I need to make the server I was working see the certificate chain. I created a GPO and applied it to the server OU. I added the Root cert to Trusted Root Certification Authorities, and I added the Cert to Trusted Publishers Certificates. Now when I open a signed script on a server, I no longer have to change the Set-ExecutionPolicy RemoteSigned and add the network path to the Local Intranet zone.
-
Powershell signing, makecert.exe and group policy – Part 1
We don’t have a pki infrastructure at my current job, and I like to keep my powershell scripts on my network drive. So I needed a way to run my .ps1 files off a network drive. Setting Set-ExecutionPolciy to Unrestricted seemed like a bad idea. So I looked into using a signed script and setting Set-ExecutionPolicy to RemoteSigned. I could not justify $300 to buy a trused third party cert, so I looked at makecert.exe from the Windows SDK.
First step make the Root CA cert, private key, and pxf.
- makecert -n “CN=RootName” -a sha1 -eku 1.3.6.1.5.5.7.3.3 -r -sv Root.pvk Root.cer
- pvk2pfx.exe -pvk Root.pvk -spc Root.cer -pfx Root.pfx -pi password
makecert and pvk2pfx can be found in the Windows SDK or in the Visual Studio bin directory. First command results in a private key (.pvk) and a certificate (.cer). Second command makes a pfx out of the first 2.
Second step is to create a certificate from the root cert above.
- makecert -pe -n “CN=Certificate” -a sha1 -eku 1.3.6.1.5.5.7.3.3 -ic Root.cer -iv Root.pvk -sv Certificate.pvk Certificate.cer
- pvk2pfx.exe -pvk Certificate.pvk -spc Certificate.cer -pfx Certificate.pfx -pi password
Now we are ready to sign our powershell script.
- $cert = Get-PfxCertificate Certificate.pfx
- Set-AuthenticodeSignature -Filepath script.ps1 -Cert $cert
Probably can be combined into one line, but I am not a guru yet.
Next post will talk about how I added this certs above to all the servers.
-
New MD5 based backup script
I found this use of md5 and find the other day. I based my current backup script around it. The md5 will show if anyone modifies a file, or adds/removes a file in the web hosting root (/var/www) or in the config directory (/etc/httpd/conf.d/). If there is a change then zip each site up individually and move to a backup folder to be rsynced to other servers.
NewWWWMD5=$(find /var/www/ -type f -exec md5sum {} \; | md5sum - | awk '{print $1}') OldWWWMD5=$(cat $PARENTDIR/_var_www_*.md5) NewConfMD5=$(find /etc/httpd/conf.d/ -type f -exec md5sum {} \; | md5sum - | awk '{print $1}') OldConfMD5=$(cat $PARENTDIR/_etc_httpd_conf.d_*.md5) if [ $NewWWWMD5 = $OldWWWMD5 -a $NewConfMD5 = $OldConfMD5 ]; then echo "Neither /var/www/ nor /etc/httpd/conf.d/ have changed" else rm -rf $BACKUPDIR/*Files echo "/var/www or /etc/httpd/conf.d has changed" mkdir -p $BACKUPDIR-Files # backup /var/www for directory in /var/www/*; do if [ -d $directory ]; then bu $directory; fi done # replace previous /var/www MD5 rm -f $PARENTDIR/_var_www_*.md5 find /var/www/ -type f -exec md5sum {} \; | md5sum - | awk '{print $1}' > $PARENTDIR/_var_www_$CURRENTDAY.md5 #backup /etc/httpd/conf.d bu "/etc/httpd/conf.d" # replace previous /etc/httpd/conf.d MD5 rm -f $PARENTDIR/_etc_httpd_conf.d_*.md5 find /etc/httpd/conf.d/ -type f -exec md5sum {} \; | md5sum - | awk '{print $1}' > $PARENTDIR/_etc_httpd_conf.d_$CURRENTDAY.md5 fiSeems to work!
-
PowerShell is great
Okay, I drank the Kool-Aid. PowerShell is awesome. The first thing I wanted to do was make sure my $profile is always the most current no matter what machine was on. In the past I had a batch file that I would run that would open my command prompt the way I wanted. I modified that so if PowerShell is installed, then get my profile up-to-date and then launch PowerShell. This is part of my current batch file:
IF NOT EXIST "c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" GOTO NO_PS powershell -NoProfile $a=(Split-Path $profile -parent);if (!(Test-Path $a)) {New-Item $a -type directory}; powershell -NoProfile if (!(Test-Path $profile)) {Copy-Item %~dp0Scripts\Microsoft.PowerShell_profile.ps1 (Split-Path $profile -parent)} powershell -NoProfile if (!(Compare-Object $(Get-Content $profile) $(Get-Content Scripts\Microsoft.PowerShell_profile.ps1)).Count -eq 0 ) {Copy-Item Scripts\Microsoft.PowerShell_profile.ps1 (Split-Path $profile -parent)} @start %COMSPEC% /K PowerShell -nologoThis will copy over my profile if it does not exist or is a different version. Now when I am on a server with PowerShell I can double click my batch file and my environment is up to date!
-
Using a sub-select to find machines that do not have the most recent version of a package.
Many people have blogged about this – how to find machines that don’t have the most recent version of a package installed.
First we write a query to show machines that don’t have the software installed (in this case firefox)select SMS_R_System.Name,SMS_R_System.LastLogonUserName from SMS_R_System inner join SMS_G_System_SYSTEM on SMS_G_System_SYSTEM.ResourceID = SMS_R_System.ResourceId where SMS_R_System.Client = 1 and SMS_G_System_SYSTEM.SystemRole = "Workstation" and SMS_G_System_SYSTEM.Name not in ( select SMS_R_System.Name from SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId where SMS_R_System.Client = 1 and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like "Mozilla Firefox%")
Next we write a query to show the machines that have the most recent software installed (this is used in the following query):select SMS_R_System.Name, SMS_R_System.LastLogonUserName, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version from SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId where SMS_R_System.Client = 1 and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like "Mozilla Firefox%" and SMS_G_System_ADD_REMOVE_PROGRAMS.Version = "3.6.3 (en-US)" order by SMS_R_System.Name
Finally we write a query to show machines that aren’t in the query above
select SMS_R_System.Name, SMS_R_System.LastLogonUserName, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version from SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId where SMS_R_System.Client = 1 and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like "Mozilla Firefox%" and SMS_R_System.Name not in ( select SMS_R_System.Name from SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId where SMS_R_System.Client = 1 and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like "Mozilla Firefox%" and SMS_G_System_ADD_REMOVE_PROGRAMS.Version = "3.6.3 (en-US)") order by SMS_R_System.Name
Import the First and Third queries into a collection and we have a collection that shows machines that need the updated package (including machines that don’t have any version of the package installed.)
-
How I created a “Copy to new item” functionality for a SharePoint list – Part 2
Second part. First Part can be found here. On the second page (NewForm.aspx), I grabbed out of the querystring the values for the source list item and the name of the list.
I used this person’s query string parser.Then I used the following SOAP query :
$(document).ready(function() { var sourceID = getQuerystring('SourceID'); var listName = getQuerystring('ListName'); var soapEnv = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'> \ <soapenv:Body> \ <GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'> \ <listName>" + listName + "</listName> \ <viewName>{GUID}</viewName> \ <viewFields /> \ <ViewFields /> \ <query> \ <Query><Where> \ <Eq> \ <FieldRef Name='ID' /> \ <Value Type='Integer'>" + sourceID + "</Value> \ </Eq> \ </Where></Query>\ </query> \ </GetListItems> \ </soapenv:Body> \ </soapenv:Envelope>"; $.ajax({ async: false, url: "http://site.com/subsite/_vti_bin/lists.asmx", type: "POST", dataType: "xml", data: soapEnv, complete: processResult, contentType: "text/xml; charset=\"utf-8\"" }); }); function processResult(xData, status) { $(xData.responseXML).find("z\\:row").each(function() { $("input[title='Input']").val($(this).attr("ows_Input")); $("textarea[title='TextArea']").val($(this).attr("ows_TextArea")); $("select[title='DropDown']").val($(this).attr("ows_DropDown")).attr("selected", "selected"); } )};In the last three lines I changed the input box, textbox and dropdown boxes to their values in the results fromt the SOAP query.
Kinda fun. Just need to figure out how to do check boxes!
-
How I created a “Copy to new item” functionality for a SharePoint list – Part 1
I wanted to create a “copy to new item” functionality for a SharePoint list.
Steps I came up with:
- The first thing I had to do was add a link to the context menu (I learned that it is called an ECB) and have it point to the NewForm.aspx.
- Once I got that, I could append a querystring variable to the url that contained the “Source ID” of the item to copy and the name of the current list.
- Then I would grab that querystring value on the other side – in the NewForm.aspx page
- Next I would use that variable to query the SharePoint List via SOAP
- Inject the results the into the form
Here is my script (add to a CEWP, I already have the jquery pointers to google in a Delegate control)
<script language="javascript"> function Custom_AddListMenuItems(m, ctx) { var editURL = window.location.protocol + "//" + window.location.host + ctx.listUrlDir + "/NewForm.aspx?SourceID=" + currentItemID + "&ListName=" + ctx.ListTitle; CAMOpt(m, "Copy To New Item" ,"window.location=('" + editURL + "');" , "/_layouts/images/Copy.GIF"); CAMSep(m); } </script>More to come.
