{"id":39,"date":"2008-08-26T10:39:38","date_gmt":"2008-08-26T01:39:38","guid":{"rendered":"http:\/\/www.jhouseconsulting.com\/index.php\/jhouseconsulting\/2008\/08\/26\/scripting-updates-to-the-gptini-for-the-local-group-policy\/"},"modified":"2010-10-28T11:06:36","modified_gmt":"2010-10-28T03:06:36","slug":"scripting-updates-to-the-gptini-for-the-local-group-policy","status":"publish","type":"post","link":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/2008\/08\/26\/scripting-updates-to-the-gptini-for-the-local-group-policy-39","title":{"rendered":"Scripting updates to the GPT.ini for the Local Group Policy"},"content":{"rendered":"<p>Updated on 27th October 2010.<\/p>\n<p>I came across a challenge whilst working on a big XenApp deployment in a Novell environment. I needed to make changes to the Local Group Policy Object on all Terminal \/ Citrix servers. This was specifically required for implementation of a logoff script, as logoff scripts are not supported via Zen Polices in a Terminal Services environment.<\/p>\n<p>As always, I wanted to automate it and found that there was a real lack of information about how this can be easily achieved. Anyway, I thought that modifying the Local Policy on all XenApp servers would be a pain, but it ended up being very simple indeed.<\/p>\n<p>Admittedly, I could have just copied a new gpt.ini and scripts.ini into place, but then it would not have respected any previous changes and settings that had already been made to the gpt.ini. So this script checks existing configuration settings before making any changes to the gpt.ini file.<\/p>\n<p>Enjoy!!<!--more--><\/p>\n<pre class=\"brush: vb; title: ; notranslate\" title=\"\">\r\n'------------------------------------------------------------------------------------------------------------\r\n' This script is used to add Logon and Logoff scripts to a local Group Policy.\r\n\r\n' It modifies\/creates the following two files needed to run logon and logoff scripts:\r\n' - &quot;%SystemRoot%\\system32\\GroupPolicy\\gpt.ini&quot;\r\n' - &quot;%SystemRoot%\\system32\\GroupPolicy\\User\\Scripts\\scripts.ini&quot;\r\n\r\n' Notes:\r\n'        - This script will modify the existing gpt.ini file, but overwrites an existing scripts.ini file.\r\n'          It does NOT append or modify the scripts.ini file.\r\n'        - This script does not copy the actual logon\/logoff scripts into place.\r\n\r\n' The motivation to write this script was to overcome some challenges in a Novell environment due to a\r\n' limitation of the integration with Novell Zen Policies, where logoff scripts are NOT supported on\r\n' Terminal Servers.\r\n\r\n' Release 1.1 Modified by Jeremy@jhouseconsulting.com on 27th October 2010.\r\n' Written by Jeremy@jhouseconsulting.com on 25th August 2008.\r\n\r\n' When managing the policy versions you should adhere to the Microsoft standards. The version numbering\r\n' differs for changes made to the User and Computer configuration. In order to track changes to each\r\n' configuration, the GPO must track a version number for each configuration. With only one version number,\r\n' the way two versions are tracked is to split the version number into two numbers.\r\n' The top 16 bits of the version number corresponds to the user configuration version. The lower 16 bits\r\n' of the version number corresponds to the computer configuration version. When looking at the version\r\n' entry in the gpt.ini file what you are then seeing is:\r\n' Version = &#x5B;user version number top 16 bits] &#x5B;computer version number lower 16 bits] \r\n' Esentially, each change to the User policy will increment the version by 131072, whilst each change to\r\n' the Computer policy will increment the version by 1.\r\n'\r\n' http:\/\/blogs.technet.com\/grouppolicy\/archive\/2007\/12\/14\/understanding-the-gpo-version-number.aspx\r\n'\r\n' For example: In this script we are making a change to the User portion of the policy by adding a\r\n' logon and logoff script. Therefore we will be incrementing the version number by 131072.\r\n'\r\n' We also need to add the Client Side Extension (CSE) GUIDs to instructs the winlogon process\r\n' to run the Startup\/Shutdown\/Logon\/Logoff scripts.\r\n' CSE GUID for script processing = {42B5FAAE-6536-11D2-AE5A-0000F87571E3}\r\n' Tool extension GUID for user and computer policy mode settings = {40B66650-4972-11D1-A7CA-0000F87571E3}\r\n'\r\n' gPCUserExtensionNames - includes a list of globally unique identifiers (GUIDs) that tells the client-side\r\n' engine which client-side extensions have User data in the Group Policy object. The format is the following:\r\n' &#x5B;{&lt;GUID of client-side extension&gt;}{&lt;GUID of MMC extension&gt;}{&lt;GUID of second MMC extension if appropriate&gt;}]\r\n'\r\n' For example: In this script we are adding logon and logoff scripts. Therefore the gPCUserExtensionNames\r\n' will be set to the following at minimum:\r\n' gPCUserExtensionNames=&#x5B;{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B66650-4972-11D1-A7CA-0000F87571E3}]\r\n'\r\n' gPCMachineExtensionNames - includes a list of GUIDs that tells the client side engine which Client Side\r\n' Extensions have Machine data in the GPO.\r\n' The default GUIDs are as follows.\r\n' gPCMachineExtensionNames=&#x5B;{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{0F6B957D-509E-11D1-A7CC-0000F87571E3}]\r\n'\r\n' gPCFunctionalityVersion - The Version number of the Group Policy extension tool that created the Group\r\n' Policy object.\r\n' The default version is 2.\r\n'\r\n' The Option setting has 4 values.\r\n' 0 = Enable User and Computer Configurations\r\n' 1 = Disable User Configuration ONLY\r\n' 2 = Disable Computer Configuration ONLY\r\n' 3 = Disable User and Computer Configurations\r\n' If the Option value is not present, the User and Computer Configurations are both enabled.\r\n'------------------------------------------------------------------------------------------------------------\r\n\r\nOption Explicit\r\n\r\nDim WshShell, strSystemRoot, strGPOLocation, objFSO, objFile, blnOption, strLine, strContents\r\nDim arrLogonScripts, arrLogoffScripts, strValue, intUserPolicy, intComputerPolicy, blnUserPolicy\r\nDim blnComputerPolicy, strCSEUserGUID, strToolextensionUserGUID, blnSection, blnUserExtensionNames\r\nDim blnVersion, blnFunctionality, blnMachineExtensionNames, i\r\n\r\nConst ForReading = 1\r\nConst ForWriting = 2\r\n\r\nSet WshShell = WScript.CreateObject(&quot;WScript.Shell&quot;)\r\nSet objFSO = CreateObject(&quot;Scripting.FileSystemObject&quot;)\r\n\r\nstrSystemRoot = WshShell.ExpandEnvironmentStrings(&quot;%SystemRoot%&quot;)\r\nstrGPOLocation = strSystemRoot &amp; &quot;\\system32\\GroupPolicy\\&quot;\r\n\r\n'********** These are the script variables that can be changed **********\r\n\r\n' Setup the arrays for the location and names of the logon and logoff scripts.\r\n' Note that if you don't want to use either one or the other, just leave the\r\n' array blank, or comment the line out altogether.\r\narrLogonScripts = Array(&quot;%SystemRoot%\\LoadQAT.cmd&quot;,&quot;%SystemRoot%\\RestoreDesktopIconPositions.Cmd&quot;)\r\narrLogoffScripts = Array(&quot;%SystemRoot%\\SaveQAT.cmd&quot;,&quot;%SystemRoot%\\SaveDesktopIconPositions.Cmd&quot;)\r\n\r\n'************************************************************************\r\n\r\nstrCSEUserGUID = &quot;{42B5FAAE-6536-11D2-AE5A-0000F87571E3}&quot;\r\nstrToolextensionUserGUID = &quot;{40B66650-4972-11D1-A7CA-0000F87571E3}&quot;\r\n\r\nblnUserPolicy = True\r\nblnComputerPolicy = False\r\n\r\nintUserPolicy = 131072\r\nintComputerPolicy = 1\r\n\r\nblnSection = False\r\nblnFunctionality = False\r\nblnMachineExtensionNames = False\r\nblnVersion = False\r\nblnUserExtensionNames = False\r\nblnOption = False\r\n\r\nIf objFSO.FileExists(strGPOLocation &amp; &quot;gpt.ini&quot;) Then\r\n  Set objFile = objFSO.OpenTextFile(strGPOLocation &amp; &quot;gpt.ini&quot;, ForReading)\r\n\r\n  Do While objFile.AtEndOfStream = False \r\n    strLine = objFile.ReadLine\r\n\r\n    If Instr(strLine,&quot;&#x5B;General]&quot;) &gt; 0 Then\r\n      blnSection = True\r\n    End If\r\n\r\n    If Len(strLine) &gt; 0 AND Instr(strLine,&quot;;&quot;) &lt;&gt; 1 AND Instr(strLine,&quot;&#x5B;General]&quot;) &lt;&gt; 1 Then\r\n    strValue=split(strLine,&quot;=&quot;)\r\n\r\n      Select Case strValue(0)\r\n        Case &quot;gPCFunctionalityVersion&quot;\r\n          blnFunctionality = True\r\n        Case &quot;gPCMachineExtensionNames&quot;\r\n          blnMachineExtensionNames = True\r\n        Case &quot;Version&quot;\r\n          If blnUserPolicy Then\r\n            strValue(1)=strValue(1) + intUserPolicy\r\n          End If\r\n          blnVersion = True\r\n        Case &quot;gPCUserExtensionNames&quot;\r\n          If trim(strValue(1))=&quot;&quot; Then\r\n            strValue(1)=&quot;&#x5B;&quot; &amp; strCSEUserGUID &amp; strToolextensionUserGUID &amp; &quot;]&quot;\r\n            blnUserExtensionNames = True\r\n          End If\r\n          If instr(strValue(1),strCSEUserGUID) &gt; 0 AND instr(strValue(1),strToolextensionUserGUID) &gt; 0 Then\r\n            blnUserExtensionNames = True\r\n          Else\r\n            If instr(strValue(1),strCSEUserGUID) = 0 Then\r\n              If Right(trim(strValue(1)),1) = &quot;]&quot; Then\r\n                strValue(1)=Left(trim(strValue(1)),Len(trim(strValue(1)))-1)\r\n              End If\r\n              strValue(1)=strValue(1) &amp; strCSEUserGUID &amp; &quot;]&quot;\r\n              blnUserExtensionNames = True\r\n            End If\r\n            If instr(strValue(1),strToolextensionUserGUID) = 0 Then\r\n              If Right(trim(strValue(1)),1) = &quot;]&quot; Then\r\n                strValue(1)=Left(trim(strValue(1)),Len(trim(strValue(1)))-1)\r\n              End If\r\n              strValue(1)=strValue(1) &amp; strToolextensionUserGUID &amp; &quot;]&quot;\r\n              blnUserExtensionNames = True\r\n            End If\r\n          End If\r\n        Case &quot;Options&quot;\r\n          If strValue(1)=&quot;0&quot; Then\r\n            blnOption = True\r\n          End If\r\n          If strValue(1)=&quot;1&quot; Then\r\n            strValue(1)=&quot;0&quot;\r\n            blnOption = True\r\n          End If\r\n          If strValue(1)=&quot;2&quot; Then\r\n            blnOption = True\r\n          End If\r\n          If strValue(1)=&quot;3&quot; Then\r\n            strValue(1)=&quot;2&quot;\r\n            blnOption = True\r\n          End If\r\n      End Select\r\n      strContents = strContents &amp; trim(strValue(0)) &amp; &quot;=&quot; &amp; trim(strValue(1)) &amp; VbCrLf\r\n    Else\r\n      strContents = strContents &amp; strLine &amp; VbCrLf\r\n    End If\r\n  Loop\r\n  objFile.Close\r\nEnd If\r\n\r\nIf blnSection = False Then\r\n  strContents=&quot;&#x5B;General]&quot; &amp; VbCrLf &amp; strContents\r\nEnd If\r\nIf blnFunctionality = False Then\r\n  strContents=strContents &amp; &quot;gPCFunctionalityVersion=2&quot; &amp; VbCrLf\r\nEnd If\r\nIf blnMachineExtensionNames = False Then\r\n  strContents=strContents &amp; &quot;gPCMachineExtensionNames=&#x5B;{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{0F6B957D-509E-11D1-A7CC-0000F87571E3}]&quot; &amp; VbCrLf\r\nEnd If\r\nIf blnVersion = False Then\r\n  If blnUserPolicy Then\r\n    strContents=strContents &amp; &quot;Version=131073&quot; &amp; VbCrLf\r\n  Else\r\n    strContents=strContents &amp; &quot;Version=1&quot; &amp; VbCrLf\r\n  End If\r\nEnd If\r\nIf blnUserExtensionNames = False Then\r\n  strContents=strContents &amp; &quot;gPCUserExtensionNames=&#x5B;&quot; &amp; strCSEUserGUID &amp; strToolextensionUserGUID &amp; &quot;]&quot; &amp; VbCrLf\r\nEnd If\r\nIf blnOption = False Then\r\n  strContents=strContents &amp; &quot;Options=0&quot; &amp; VbCrLf\r\nEnd If\r\n\r\nSet objFile = objFSO.OpenTextFile(strGPOLocation &amp; &quot;gpt.ini&quot;, ForWriting, True)\r\nobjFile.Write(strContents)\r\nobjFile.Close\r\nSet objFile = Nothing\r\n\r\nWScript.Echo &quot;Local GPO Updated (gpt.ini): &quot; &amp; chr(34) &amp; strGPOLocation &amp; &quot;gpt.ini&quot; &amp; chr(34)\r\n\r\nIf NOT objfso.FolderExists(strGPOLocation &amp; &quot;User&quot;) Then\r\n  objfso.CreateFolder(strGPOLocation &amp; &quot;User&quot;)\r\nEnd If\r\nIf NOT objfso.FolderExists(strGPOLocation &amp; &quot;User\\Scripts&quot;) Then\r\n  objfso.CreateFolder(strGPOLocation &amp; &quot;User\\Scripts&quot;)\r\nEnd If\r\nIf NOT objfso.FolderExists(strGPOLocation &amp; &quot;User\\Scripts\\Logoff&quot;) Then\r\n  objfso.CreateFolder(strGPOLocation &amp; &quot;User\\Scripts\\Logoff&quot;)\r\nEnd If\r\nIf NOT objfso.FolderExists(strGPOLocation &amp; &quot;User\\Scripts\\Logon&quot;) Then\r\n  objfso.CreateFolder(strGPOLocation &amp; &quot;User\\Scripts\\Logon&quot;)\r\nEnd If\r\n\r\n' Need to unhide the scripts.ini file to prevent any &quot;permission denied&quot; errors.\r\nIf objfso.FileExists(strGPOLocation &amp; &quot;User\\Scripts\\scripts.ini&quot;) Then\r\n  Set objFile = objFSO.GetFile(strGPOLocation &amp; &quot;User\\Scripts\\scripts.ini&quot;)\r\n  If objFile.Attributes = objFile.Attributes AND 2 Then\r\n    objFile.Attributes = objFile.Attributes XOR 2\r\n  End If\r\n  Set objFile = Nothing\r\nEnd If\r\n\r\nstrContents = &quot;&#x5B;Logon]&quot; &amp; VbCrLf\r\nIf IsArray(arrLogonScripts) Then\r\n  For i = 0 to ubound(arrLogonScripts)\r\n    strContents = strContents &amp; i &amp; &quot;CmdLine=&quot; &amp; arrLogonScripts(i) &amp; VbCrLf\r\n    strContents = strContents &amp; i &amp; &quot;Parameters=&quot; &amp; VbCrLf\r\n  Next\r\nEnd If\r\nstrContents = strContents &amp; &quot;&#x5B;Logoff]&quot; &amp; VbCrLf\r\nIf IsArray(arrLogoffScripts) Then\r\n  For i = 0 to ubound(arrLogoffScripts)\r\n    strContents = strContents &amp; i &amp; &quot;CmdLine=&quot; &amp; arrLogoffScripts(i) &amp; VbCrLf\r\n    strContents = strContents &amp; i &amp; &quot;Parameters=&quot; &amp; VbCrLf\r\n  Next\r\nEnd If\r\n\r\nOn Error Resume Next\r\nSet objFile = objFSO.OpenTextFile(strGPOLocation &amp; &quot;User\\Scripts\\scripts.ini&quot;, ForWriting, True)\r\nIf Err.Number = 0 Then\r\n  objFile.Write(strContents)\r\n  objFile.Close\r\n  Set objFile = Nothing\r\n  WScript.Echo &quot;Scripts Added (scripts.ini): &quot; &amp; chr(34) &amp; strGPOLocation &amp; &quot;User\\Scripts\\scripts.ini&quot; &amp; chr(34)\r\n' Hide the scripts.ini file.\r\n  Set objFile = objFSO.GetFile(strGPOLocation &amp; &quot;User\\Scripts\\scripts.ini&quot;)\r\n  objFile.Attributes = objFile.Attributes XOR 2\r\n  Set objFile = Nothing\r\nElse\r\n  wscript.echo &quot;Error: &quot; &amp; Err.Description &amp; &quot;. The scripts.ini file has not been set.&quot;\r\nEnd If\r\nOn Error Goto 0\r\n\r\nSet WshShell = Nothing\r\nSet objFSO = Nothing\r\n\r\nwscript.quit (0)\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Updated on 27th October 2010. I came across a challenge whilst working on a big XenApp deployment in a Novell environment. I needed to make changes to the Local Group Policy Object on all Terminal \/ Citrix servers. This was specifically required for implementation of a logoff script, as logoff scripts are not supported via &#8230; <a title=\"Scripting updates to the GPT.ini for the Local Group Policy\" class=\"read-more\" href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/2008\/08\/26\/scripting-updates-to-the-gptini-for-the-local-group-policy-39\" aria-label=\"Read more about Scripting updates to the GPT.ini for the Local Group Policy\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[60,55,5],"tags":[416,63,61,66,67,53,54,201,418,65,200,62,64,417],"class_list":["post-39","post","type-post","status-publish","format-standard","hentry","category-group-policy","category-novell","category-scripting","tag-citrix","tag-gpcuserextensionnames","tag-gptini","tag-local-group-policy","tag-local-policy","tag-local-user-policy","tag-logoff-script","tag-logon-script","tag-novell","tag-options","tag-scripts-ini","tag-vbscript","tag-version","tag-xenapp"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/39","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/comments?post=39"}],"version-history":[{"count":6,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/39\/revisions"}],"predecessor-version":[{"id":703,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/39\/revisions\/703"}],"wp:attachment":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/media?parent=39"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/categories?post=39"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/tags?post=39"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}