Hey, Scripting Guy! The script you wrote yesterday to check the status of offline files was pretty cool. However, it does not help me if I want to enable or disable offline files on my computer. Do you have a script to allow me to actually dooooooooo something?
– LS
Hi LS,
Doooooooooo we have a script that actually does something? Of course we do. We are outside playing Frisbee golf on the green lawn here on campus. Scripting Guy Ed Wilson is sitting under a tree, ostensibly watching us, but we suspect he is actually writing a script. This guy writes scripts in his sleep (or so we have been told). Hey, Ed, can you write a script to enable and disable offline files? LS, we will get back with you. It is our turn to putt (said in the whisper of Jim Nantz).
Okay, we are back. Ed has cooked up a pretty good one today. He calls it the EnableDisableOfflineFiles.ps1 script. He must be feeling creative. Here it is in its entirety.
EnableDisableOfflineFiles.ps1
param($computer=”localhost”, $a, $help)function funline ($strIN) { $num = $strIN.length for($i=1 ; $i -le $num ; $i++) { $funline += “=” } Write-Host -ForegroundColor yellow $strIN Write-Host -ForegroundColor darkYellow $funline }
function funHelp() { $helpText=@” DESCRIPTION: NAME: EnableDisableOffLineFiles.ps1 Enables or disables offline files on a local or remote machine. A reboot of the machine MAY be required. This information will be displayed in the status message once the script is run.
PARAMETERS: -computer Specifies name of the computer upon which to run the script -a(ction) < e(nable), d(isable) > -help prints help file
SYNTAX: EnableDisableOffLineFiles.ps1 -computer MunichServer -a e
Enables offline files on a computer named MunichServer
EnableDisableOffLineFiles.ps1 -a d
Disables offline files on local computer
EnableDisableOffLineFiles.ps1 -help ?
Displays the help topic for the script
“@ $helpText exit }
function funtranslatemethod($a) { switch($a) { “e” { $glogal:m = $true $global:msg = “Enable offline files” } “d” { $global:m = $false $global:msg = “Disable offline files” } default{ $global:msg = “$a is not an allowed response`n” } } }
if($help){ funline(“Obtaining help …”) ; funhelp } if(!$a) { $(throw “You must supply an action. try this: EnableDIsableOfflineFiles.ps1 -help ?”) } $global:msg =$global:m = $null funtranslatemethod($a)
$objWMI = [wmiclass]”\\$computer\root\cimv2:win32_offlinefilescache” funline(“Configure Offline files on $computer …”) $rtn = $objwmi.enable($m) if($rtn.returnvalue -eq 0) { Write-Host -ForegroundColor green “$msg succeeded” } ELSE { Write-Host -ForegroundColor red “$msg failed with $($rtn.returnvalue) ” } if($rtn.rebootrequired) { Write-Host -ForegroundColor cyan “reboot required” }
To enable or to disable the offline files feature on more than one machine or as part of a standard build process, you can use the EnableDisableOfflineFiles.ps1 script. This script leverages the WIN32_Offlinefilescache WMI class.
The EnableDisableOfflineFiles.ps1 script begins with the param statement. The param statement is used to provide us with the ability to specify named arguments to the script when it runs. This gives the ability to control how the script executes without having to edit the script. The first parameter defined is the –computer parameter. The $computer variable is automatically created to hold the data supplied when the script is run. However, we decided to set the variable to a default value of localhost. This allows us to run the script against the local machine without having to actually supply a value to use. We define two other parameters: -a and –help. We do not assign default values to these variables. The –a parameter will be used to specify the action to perform when the script is run. The –help parameter determines whether or not the Help text is displayed. This line of code is seen here:
param($computer=”localhost”, $a, $help)
Next, we have the funline function. The funline function is used to underline the output from the script and to provide a visual reference point to make the output easier to read and to understand. We declare a single input statement to the function, which is called $strIN. The input string is whatever is passed to the funline function. We use the length property to determine the length of the line that was passed to the function. We store the length of the string in the b variable, and use it in the for loop. We begin counting at 1 and will continue looping until the value of $i (the counter variable) is less than or equal to the sum stored in the $num variable. We then increment the value of $i by 1 ($i++). The code that is run as a result of the for loop is used to build up the variable $funline with a group of equal signs (“=”). We then use the Write-Host cmdlet to print out the input string. We specify the –foregroundcolor parameter of yellow, and the line separator contained in the $funline function is printed out using the –foregroundcolor parameter of darkyellow. This gives a nice visual effect to the line separator. This function is seen here:
function funline ($strIN) { $num = $strIN.length for($i=1 ; $i -le $num ; $i++) { $funline += “=” } Write-Host -ForegroundColor yellow $strIN Write-Host -ForegroundColor darkYellow $funline }
Now we come to the funHelp function. This function is used to display a Help message to the user when the script is run with the –help parameter specified. There are no input parameters defined for this function. We begin the function by declaring the variable $helpText and opening a here-string. The here-string is opened by using the special character combination @”. The here-string uses the same character combination in reverse “@ to end the here-string. The advantage of using the here-string is that it allows us to ignore quoting rules, and simply type the text as we wish it to appear in the output. In the here-string, we define sections of Help such as a general description of the script, the parameters the script requires, and several syntax examples. The funHelp function ends by displaying the contents of the $helpText variable and calling the exit statement. The entire funHelp function is seen here:
function funHelp() { $helpText=@” DESCRIPTION: NAME: EnableDisableOffLineFiles.ps1 Enables or disables offline files on a local or remote machine. A reboot of the machine MAY be required. This information will be displayed in the status message once the script is run.PARAMETERS: -computer Specifies name of the computer upon which to run the script -a(ction) < e(nable), d(isable) > -help prints help file
SYNTAX: EnableDisableOffLineFiles.ps1 -computer MunichServer -a e
Enables offline files on a computer named MunichServer
EnableDisableOffLineFiles.ps1 -a d
Disables offline files on local computer
EnableDisableOffLineFiles.ps1 -help ?
Displays the help topic for the script
“@ $helpText exit }
After we are finished with the funhelp function, we move on to declare an additional function—the funtranslatemethod function. The funtranslatemethod function is used to translate the input parameter that is specified for the –a (action) parameter. The value that will be contained in the $a variable is supplied when the script is run. In fact, this script will generate an error if the –a parameter is missing when the script is run. This makes sense because you need to know if you want to either enable or disable offline files before you run the script.
The funtranslatemethod function uses the switch statement to evaluate the value that was supplied to the –a parameter. If the value contained in the $a variable is the letter e, we do two things inside the code block. We first assign the intrinsic variable $true to the global variable $m. The second thing we do is use the global variable $msg and store the string we will display to the user. We use the string “Enable offline files” to indicate the action we were trying to perform.
The other action we have defined in the funtranslatemethod function is the disable action. If the user supplies the letter b to the script when it is run, we will use the global variable $m to hold the intrinsic variable b. This will be supplied to the method call in the main body of the script a little bit later. We also store a string—“Disable offline files”—in the global variable $msg.
The default action of the switch statement is to store the string “is not an allowed response” in the global variable $msg. We also print out the value of the action that was contained in the $a variable, and use a special character “`n” to cause the string to be printed with a new line character at the end of the string. The complete funtranslatemethod function is seen here:
function funtranslatemethod($a) { switch($a) { “e” { $global:m = $true $global:msg = “Enable offline files” } “d” { $global:m = $false $global:msg = “Disable offline files” } default{ $global:msg = “$a is not an allowed response`n” } } }
Now we need to check for the presence of a couple of variables. The first variable we want to check for is the $help variable. If it is present, it means the script was run with the –help parameter, and we want to display the help text as a result. To do this, we use the if statement and look for the variable. If it is found, in our code block we call the funline function to display a string message, and then call the funhelp function. This line of code is seen here:
if($help){ funline(“Obtaining help …”) ; funhelp }
Next we look for the presence of the $a variable. If it is not present, it means the script was run without the $a parameter. We want this parameter to be a required parameter, and as a result, we use the throw statement to display a message. When we use the throw statement, it will halt execution of the script and display our message in red. This is similar to using the raise method of the error object in other programming languages.
The string that we will “throw” is used to indicate the error that occurred—a value for the –a parameter was not supplied. This error is shown here:
We then point the user to the Help file:
if(!$a) { $(throw “You must supply an action. try this: EnableDIsableOfflineFiles.ps1 -help ?”) }
If the user does not want to see the Help file, and they have supplied a value for the action parameter, we declare a couple of global variables, set them to null, and then call the funtranslatemethod function to see which action we need to perform. These two lines of code are seen here:
$global:msg = $global:m = $null funtranslatemethod($a)
It is now time to make the connection into WMI. To do this, we use the [wmiclass] type accelerator, which provides access to the system.management.managementobject .NET Framework class. This .NET Framework class provides access to the WMI methods that might not be available when using the Get-Wmiobject cmdlet. Luckily, we can use the Get-Member cmdlet and the Windows Software Development Kit (SDK) to provide additional information about calling the methods. The syntax to connect to a remote computer using this class is a bit strange as seen below. We incorporate the $computer variable that is supplied from the command line into the connection string to make it easy to target other computers. We store the system.management.managementobject that is created in the $objWMI variable. This line of code is seen here:
$objWMI = [wmiclass]”\\$computer\root\cimv2:win32_offlinefilescache”
Now we want to call the enable method, and either enable or disable the use of the offline files feature in Windows Server 2008 R2 or Windows Vista. We use the funline function to print out the status message, and then we call the enable() method. This code is seen here:
funline(“Configure Offline files on $computer …”) $rtn = $objwmi.enable($m)
Next, we want to evaluate the return code that came back from calling the enable method on the machine. If the returnvalue property of the return code is equal to 0, the call succeeded. Otherwise, we print out the return code and state the call was not successful. The problem with this WMI class is that it does not always supply a non-zero return value. However, the class always returns a 0 when it succeeds. This code is seen here:
if($rtn.returnvalue -eq 0) { Write-Host -ForegroundColor green “$msg succeeded” } ELSE { Write-Host -ForegroundColor red “$msg failed with $($rtn.returnvalue) ” }
We also need to check the rebootrequired property. When the enable method “works” but detects that a reboot is required, it will set the rebootrequired property. We look for it and display that the reboot is required. This code is seen here:
if($rtn.rebootrequired) { Write-Host -ForegroundColor cyan “reboot required” }
LS, we got a hole in one in our Frisbee golf game, and Ed appears to have scored a hole in one with the EnableDisableOfflineFiles.ps1 script. Join us tomorrow as we continue Managing User Data Week. Hey, the Summer Scripting Games are nearly upon us. We will begin revealing the event scenarios next week. So stay tuned.
Ed Wilson and Craig Liebendorfer, Scripting Guys
0 comments